From d04fab38eb639e3c218c3d510241256493fb759d Mon Sep 17 00:00:00 2001
From: Denis Kasak <dkasak@termina.org.uk>
Date: Fri, 12 Apr 2024 13:28:16 +0200
Subject: [PATCH 1/2] Add CODEOWNERS.

---
 .github/CODEOWNERS | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 .github/CODEOWNERS

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 00000000..dbe9139e
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+*  @dkasak @poljar

From cfeb1b124459ae3cb396aa75706c9d849e1c407b Mon Sep 17 00:00:00 2001
From: Johannes Marbach <n0-0ne+github@mailbox.org>
Date: Sat, 20 Apr 2024 09:31:20 +0200
Subject: [PATCH 2/2] chore: Fix clippy warnings about non-local impl
 definition (#145)

Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
---
 src/megolm/group_session.rs         |  62 +++----
 src/megolm/inbound_group_session.rs |  87 +++++-----
 src/olm/session/mod.rs              | 251 +++++++++++++++-------------
 3 files changed, 213 insertions(+), 187 deletions(-)

diff --git a/src/megolm/group_session.rs b/src/megolm/group_session.rs
index 62bc5f26..194a2438 100644
--- a/src/megolm/group_session.rs
+++ b/src/megolm/group_session.rs
@@ -146,40 +146,46 @@ impl GroupSession {
         pickle: &str,
         pickle_key: &[u8],
     ) -> Result<Self, crate::LibolmPickleError> {
-        use matrix_pickle::Decode;
-        use zeroize::Zeroize;
+        use crate::{megolm::group_session::libolm_compat::Pickle, utilities::unpickle_libolm};
 
-        use crate::{
-            megolm::libolm::LibolmRatchetPickle,
-            utilities::{unpickle_libolm, LibolmEd25519Keypair},
-        };
+        const PICKLE_VERSION: u32 = 1;
+        unpickle_libolm::<Pickle, _>(pickle, pickle_key, PICKLE_VERSION)
+    }
+}
 
-        #[derive(Zeroize, Decode)]
-        #[zeroize(drop)]
-        struct Pickle {
-            version: u32,
-            ratchet: LibolmRatchetPickle,
-            ed25519_keypair: LibolmEd25519Keypair,
-        }
+#[cfg(feature = "libolm-compat")]
+mod libolm_compat {
+    use matrix_pickle::Decode;
+    use zeroize::Zeroize;
+
+    use super::GroupSession;
+    use crate::{
+        megolm::{libolm::LibolmRatchetPickle, SessionConfig},
+        utilities::LibolmEd25519Keypair,
+        Ed25519Keypair,
+    };
+
+    #[derive(Zeroize, Decode)]
+    #[zeroize(drop)]
+    pub(super) struct Pickle {
+        version: u32,
+        ratchet: LibolmRatchetPickle,
+        ed25519_keypair: LibolmEd25519Keypair,
+    }
 
-        impl TryFrom<Pickle> for GroupSession {
-            type Error = crate::LibolmPickleError;
+    impl TryFrom<Pickle> for GroupSession {
+        type Error = crate::LibolmPickleError;
 
-            fn try_from(pickle: Pickle) -> Result<Self, Self::Error> {
-                // Removing the borrow doesn't work and clippy complains about
-                // this on nightly.
-                #[allow(clippy::needless_borrow)]
-                let ratchet = (&pickle.ratchet).into();
-                let signing_key =
-                    Ed25519Keypair::from_expanded_key(&pickle.ed25519_keypair.private_key)?;
+        fn try_from(pickle: Pickle) -> Result<Self, Self::Error> {
+            // Removing the borrow doesn't work and clippy complains about
+            // this on nightly.
+            #[allow(clippy::needless_borrow)]
+            let ratchet = (&pickle.ratchet).into();
+            let signing_key =
+                Ed25519Keypair::from_expanded_key(&pickle.ed25519_keypair.private_key)?;
 
-                Ok(Self { ratchet, signing_key, config: SessionConfig::version_1() })
-            }
+            Ok(Self { ratchet, signing_key, config: SessionConfig::version_1() })
         }
-
-        const PICKLE_VERSION: u32 = 1;
-
-        unpickle_libolm::<Pickle, _>(pickle, pickle_key, PICKLE_VERSION)
     }
 }
 
diff --git a/src/megolm/inbound_group_session.rs b/src/megolm/inbound_group_session.rs
index 233d52c7..aeab6763 100644
--- a/src/megolm/inbound_group_session.rs
+++ b/src/megolm/inbound_group_session.rs
@@ -19,7 +19,6 @@ use hmac::digest::MacError;
 use serde::{Deserialize, Serialize};
 use subtle::ConstantTimeEq;
 use thiserror::Error;
-use zeroize::Zeroize;
 
 use super::{
     default_config,
@@ -371,50 +370,60 @@ impl InboundGroupSession {
         pickle: &str,
         pickle_key: &[u8],
     ) -> Result<Self, crate::LibolmPickleError> {
-        use matrix_pickle::Decode;
-
-        use super::libolm::LibolmRatchetPickle;
-        use crate::utilities::unpickle_libolm;
-
-        #[derive(Zeroize, Decode)]
-        #[zeroize(drop)]
-        struct Pickle {
-            version: u32,
-            initial_ratchet: LibolmRatchetPickle,
-            latest_ratchet: LibolmRatchetPickle,
-            signing_key: [u8; 32],
-            signing_key_verified: bool,
-        }
-
-        impl TryFrom<Pickle> for InboundGroupSession {
-            type Error = crate::LibolmPickleError;
-
-            fn try_from(pickle: Pickle) -> Result<Self, Self::Error> {
-                // Removing the borrow doesn't work and clippy complains about
-                // this on nightly.
-                #[allow(clippy::needless_borrow)]
-                let initial_ratchet = (&pickle.initial_ratchet).into();
-                #[allow(clippy::needless_borrow)]
-                let latest_ratchet = (&pickle.latest_ratchet).into();
-                let signing_key = Ed25519PublicKey::from_slice(&pickle.signing_key)?;
-                let signing_key_verified = pickle.signing_key_verified;
-
-                Ok(Self {
-                    initial_ratchet,
-                    latest_ratchet,
-                    signing_key,
-                    signing_key_verified,
-                    config: SessionConfig::version_1(),
-                })
-            }
-        }
+        use crate::{
+            megolm::inbound_group_session::libolm_compat::Pickle, utilities::unpickle_libolm,
+        };
 
         const PICKLE_VERSION: u32 = 2;
-
         unpickle_libolm::<Pickle, _>(pickle, pickle_key, PICKLE_VERSION)
     }
 }
 
+#[cfg(feature = "libolm-compat")]
+mod libolm_compat {
+    use matrix_pickle::Decode;
+    use zeroize::Zeroize;
+
+    use super::InboundGroupSession;
+    use crate::{
+        megolm::{libolm::LibolmRatchetPickle, SessionConfig},
+        Ed25519PublicKey,
+    };
+
+    #[derive(Zeroize, Decode)]
+    #[zeroize(drop)]
+    pub(super) struct Pickle {
+        version: u32,
+        initial_ratchet: LibolmRatchetPickle,
+        latest_ratchet: LibolmRatchetPickle,
+        signing_key: [u8; 32],
+        signing_key_verified: bool,
+    }
+
+    impl TryFrom<Pickle> for InboundGroupSession {
+        type Error = crate::LibolmPickleError;
+
+        fn try_from(pickle: Pickle) -> Result<Self, Self::Error> {
+            // Removing the borrow doesn't work and clippy complains about
+            // this on nightly.
+            #[allow(clippy::needless_borrow)]
+            let initial_ratchet = (&pickle.initial_ratchet).into();
+            #[allow(clippy::needless_borrow)]
+            let latest_ratchet = (&pickle.latest_ratchet).into();
+            let signing_key = Ed25519PublicKey::from_slice(&pickle.signing_key)?;
+            let signing_key_verified = pickle.signing_key_verified;
+
+            Ok(Self {
+                initial_ratchet,
+                latest_ratchet,
+                signing_key,
+                signing_key_verified,
+                config: SessionConfig::version_1(),
+            })
+        }
+    }
+}
+
 /// A format suitable for serialization which implements [`serde::Serialize`]
 /// and [`serde::Deserialize`]. Obtainable by calling
 /// [`InboundGroupSession::pickle`].
diff --git a/src/olm/session/mod.rs b/src/olm/session/mod.rs
index 8b9a9f16..59c72a20 100644
--- a/src/olm/session/mod.rs
+++ b/src/olm/session/mod.rs
@@ -32,7 +32,6 @@ use receiver_chain::ReceiverChain;
 use root_key::RemoteRootKey;
 use serde::{Deserialize, Serialize};
 use thiserror::Error;
-use zeroize::Zeroize;
 
 use super::{
     session_config::Version,
@@ -329,144 +328,156 @@ impl Session {
         pickle: &str,
         pickle_key: &[u8],
     ) -> Result<Self, crate::LibolmPickleError> {
-        use chain_key::ChainKey;
-        use matrix_pickle::Decode;
-        use message_key::RemoteMessageKey;
-        use ratchet::{Ratchet, RatchetKey};
-        use root_key::RootKey;
-
-        use crate::{types::Curve25519SecretKey, utilities::unpickle_libolm};
-
-        #[derive(Debug, Decode, Zeroize)]
-        #[zeroize(drop)]
-        struct SenderChain {
-            public_ratchet_key: [u8; 32],
-            #[secret]
-            secret_ratchet_key: Box<[u8; 32]>,
-            chain_key: Box<[u8; 32]>,
-            chain_key_index: u32,
-        }
+        use crate::{olm::session::libolm_compat::Pickle, utilities::unpickle_libolm};
 
-        #[derive(Debug, Decode, Zeroize)]
-        #[zeroize(drop)]
-        struct ReceivingChain {
-            public_ratchet_key: [u8; 32],
-            #[secret]
-            chain_key: Box<[u8; 32]>,
-            chain_key_index: u32,
-        }
+        const PICKLE_VERSION: u32 = 1;
+        unpickle_libolm::<Pickle, _>(pickle, pickle_key, PICKLE_VERSION)
+    }
+}
 
-        impl From<&ReceivingChain> for ReceiverChain {
-            fn from(chain: &ReceivingChain) -> Self {
-                let ratchet_key = RemoteRatchetKey::from(chain.public_ratchet_key);
-                let chain_key = RemoteChainKey::from_bytes_and_index(
-                    chain.chain_key.clone(),
-                    chain.chain_key_index,
-                );
+#[cfg(feature = "libolm-compat")]
+mod libolm_compat {
+    use matrix_pickle::Decode;
+    use zeroize::Zeroize;
+
+    use super::{
+        chain_key::{ChainKey, RemoteChainKey},
+        double_ratchet::{DoubleRatchet, RatchetCount},
+        message_key::RemoteMessageKey,
+        ratchet::{Ratchet, RatchetKey, RemoteRatchetKey},
+        receiver_chain::ReceiverChain,
+        root_key::{RemoteRootKey, RootKey},
+        ChainStore, Session,
+    };
+    use crate::{
+        olm::{SessionConfig, SessionKeys},
+        types::Curve25519SecretKey,
+        Curve25519PublicKey,
+    };
 
-                ReceiverChain::new(ratchet_key, chain_key, RatchetCount::unknown())
-            }
-        }
+    #[derive(Debug, Decode, Zeroize)]
+    #[zeroize(drop)]
+    struct SenderChain {
+        public_ratchet_key: [u8; 32],
+        #[secret]
+        secret_ratchet_key: Box<[u8; 32]>,
+        chain_key: Box<[u8; 32]>,
+        chain_key_index: u32,
+    }
+
+    #[derive(Debug, Decode, Zeroize)]
+    #[zeroize(drop)]
+    struct ReceivingChain {
+        public_ratchet_key: [u8; 32],
+        #[secret]
+        chain_key: Box<[u8; 32]>,
+        chain_key_index: u32,
+    }
+
+    impl From<&ReceivingChain> for ReceiverChain {
+        fn from(chain: &ReceivingChain) -> Self {
+            let ratchet_key = RemoteRatchetKey::from(chain.public_ratchet_key);
+            let chain_key = RemoteChainKey::from_bytes_and_index(
+                chain.chain_key.clone(),
+                chain.chain_key_index,
+            );
 
-        #[derive(Debug, Decode, Zeroize)]
-        #[zeroize(drop)]
-        struct MessageKey {
-            ratchet_key: [u8; 32],
-            #[secret]
-            message_key: Box<[u8; 32]>,
-            index: u32,
+            ReceiverChain::new(ratchet_key, chain_key, RatchetCount::unknown())
         }
+    }
 
-        impl From<&MessageKey> for RemoteMessageKey {
-            fn from(key: &MessageKey) -> Self {
-                RemoteMessageKey { key: key.message_key.clone(), index: key.index.into() }
-            }
-        }
+    #[derive(Debug, Decode, Zeroize)]
+    #[zeroize(drop)]
+    struct MessageKey {
+        ratchet_key: [u8; 32],
+        #[secret]
+        message_key: Box<[u8; 32]>,
+        index: u32,
+    }
 
-        #[derive(Decode)]
-        struct Pickle {
-            #[allow(dead_code)]
-            version: u32,
-            #[allow(dead_code)]
-            received_message: bool,
-            session_keys: SessionKeys,
-            #[secret]
-            root_key: Box<[u8; 32]>,
-            sender_chains: Vec<SenderChain>,
-            receiver_chains: Vec<ReceivingChain>,
-            message_keys: Vec<MessageKey>,
+    impl From<&MessageKey> for RemoteMessageKey {
+        fn from(key: &MessageKey) -> Self {
+            RemoteMessageKey { key: key.message_key.clone(), index: key.index.into() }
         }
+    }
 
-        impl Drop for Pickle {
-            fn drop(&mut self) {
-                self.root_key.zeroize();
-                self.sender_chains.zeroize();
-                self.receiver_chains.zeroize();
-                self.message_keys.zeroize();
-            }
+    #[derive(Decode)]
+    pub(super) struct Pickle {
+        #[allow(dead_code)]
+        version: u32,
+        #[allow(dead_code)]
+        received_message: bool,
+        session_keys: SessionKeys,
+        #[secret]
+        root_key: Box<[u8; 32]>,
+        sender_chains: Vec<SenderChain>,
+        receiver_chains: Vec<ReceivingChain>,
+        message_keys: Vec<MessageKey>,
+    }
+
+    impl Drop for Pickle {
+        fn drop(&mut self) {
+            self.root_key.zeroize();
+            self.sender_chains.zeroize();
+            self.receiver_chains.zeroize();
+            self.message_keys.zeroize();
         }
+    }
 
-        impl TryFrom<Pickle> for Session {
-            type Error = crate::LibolmPickleError;
+    impl TryFrom<Pickle> for Session {
+        type Error = crate::LibolmPickleError;
 
-            fn try_from(pickle: Pickle) -> Result<Self, Self::Error> {
-                let mut receiving_chains = ChainStore::new();
+        fn try_from(pickle: Pickle) -> Result<Self, Self::Error> {
+            let mut receiving_chains = ChainStore::new();
 
-                for chain in &pickle.receiver_chains {
-                    receiving_chains.push(chain.into())
-                }
+            for chain in &pickle.receiver_chains {
+                receiving_chains.push(chain.into())
+            }
 
-                for key in &pickle.message_keys {
-                    let ratchet_key =
-                        RemoteRatchetKey::from(Curve25519PublicKey::from(key.ratchet_key));
+            for key in &pickle.message_keys {
+                let ratchet_key =
+                    RemoteRatchetKey::from(Curve25519PublicKey::from(key.ratchet_key));
 
-                    if let Some(receiving_chain) = receiving_chains.find_ratchet(&ratchet_key) {
-                        receiving_chain.insert_message_key(key.into())
-                    }
+                if let Some(receiving_chain) = receiving_chains.find_ratchet(&ratchet_key) {
+                    receiving_chain.insert_message_key(key.into())
                 }
+            }
 
-                if let Some(chain) = pickle.sender_chains.first() {
-                    // XXX: Passing in secret array as value.
-                    let ratchet_key = RatchetKey::from(Curve25519SecretKey::from_slice(
-                        chain.secret_ratchet_key.as_ref(),
-                    ));
-                    let chain_key = ChainKey::from_bytes_and_index(
-                        chain.chain_key.clone(),
-                        chain.chain_key_index,
-                    );
-
-                    let root_key = RootKey::new(pickle.root_key.clone());
-
-                    let ratchet = Ratchet::new_with_ratchet_key(root_key, ratchet_key);
-                    let sending_ratchet =
-                        DoubleRatchet::from_ratchet_and_chain_key(ratchet, chain_key);
-
-                    Ok(Self {
-                        session_keys: pickle.session_keys,
-                        sending_ratchet,
-                        receiving_chains,
-                        config: SessionConfig::version_1(),
-                    })
-                } else if let Some(chain) = receiving_chains.get(0) {
-                    let sending_ratchet = DoubleRatchet::inactive_from_libolm_pickle(
-                        RemoteRootKey::new(pickle.root_key.clone()),
-                        chain.ratchet_key(),
-                    );
-
-                    Ok(Self {
-                        session_keys: pickle.session_keys,
-                        sending_ratchet,
-                        receiving_chains,
-                        config: SessionConfig::version_1(),
-                    })
-                } else {
-                    Err(crate::LibolmPickleError::InvalidSession)
-                }
+            if let Some(chain) = pickle.sender_chains.first() {
+                // XXX: Passing in secret array as value.
+                let ratchet_key = RatchetKey::from(Curve25519SecretKey::from_slice(
+                    chain.secret_ratchet_key.as_ref(),
+                ));
+                let chain_key =
+                    ChainKey::from_bytes_and_index(chain.chain_key.clone(), chain.chain_key_index);
+
+                let root_key = RootKey::new(pickle.root_key.clone());
+
+                let ratchet = Ratchet::new_with_ratchet_key(root_key, ratchet_key);
+                let sending_ratchet = DoubleRatchet::from_ratchet_and_chain_key(ratchet, chain_key);
+
+                Ok(Self {
+                    session_keys: pickle.session_keys,
+                    sending_ratchet,
+                    receiving_chains,
+                    config: SessionConfig::version_1(),
+                })
+            } else if let Some(chain) = receiving_chains.get(0) {
+                let sending_ratchet = DoubleRatchet::inactive_from_libolm_pickle(
+                    RemoteRootKey::new(pickle.root_key.clone()),
+                    chain.ratchet_key(),
+                );
+
+                Ok(Self {
+                    session_keys: pickle.session_keys,
+                    sending_ratchet,
+                    receiving_chains,
+                    config: SessionConfig::version_1(),
+                })
+            } else {
+                Err(crate::LibolmPickleError::InvalidSession)
             }
         }
-
-        const PICKLE_VERSION: u32 = 1;
-        unpickle_libolm::<Pickle, _>(pickle, pickle_key, PICKLE_VERSION)
     }
 }