Skip to main content

core_crypto/proteus/
core_crypto.rs

1use super::ProteusCentral;
2use crate::{CoreCrypto, Error, Result};
3
4impl CoreCrypto {
5    /// Proteus session exists
6    ///
7    /// Warning: The Proteus client **MUST** be initialized with
8    /// [crate::transaction_context::TransactionContext::proteus_init] first or an error will be
9    /// returned
10    pub async fn proteus_session_exists(&self, session_id: &str) -> Result<bool> {
11        let mut mutex = self.proteus.lock().await;
12        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
13        Ok(proteus.session_exists(session_id, &self.database).await)
14    }
15
16    /// Returns the proteus last resort prekey id (u16::MAX = 65535)
17    pub fn proteus_last_resort_prekey_id() -> u16 {
18        ProteusCentral::last_resort_prekey_id()
19    }
20
21    /// Returns the proteus identity's public key fingerprint
22    ///
23    /// Warning: The Proteus client **MUST** be initialized with
24    /// [crate::transaction_context::TransactionContext::proteus_init] first or an error will be
25    /// returned
26    pub async fn proteus_fingerprint(&self) -> Result<String> {
27        let mutex = self.proteus.lock().await;
28        let proteus = mutex.as_ref().ok_or(Error::ProteusNotInitialized)?;
29        Ok(proteus.fingerprint())
30    }
31
32    /// Returns the proteus identity's public key fingerprint
33    ///
34    /// Warning: The Proteus client **MUST** be initialized with
35    /// [crate::transaction_context::TransactionContext::proteus_init] first or an error will be
36    /// returned
37    pub async fn proteus_fingerprint_local(&self, session_id: &str) -> Result<String> {
38        let mut mutex = self.proteus.lock().await;
39        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
40        proteus.fingerprint_local(session_id, &self.database).await
41    }
42
43    /// Returns the proteus identity's public key fingerprint
44    ///
45    /// Warning: The Proteus client **MUST** be initialized with
46    /// [crate::transaction_context::TransactionContext::proteus_init] first or an error will be
47    /// returned
48    pub async fn proteus_fingerprint_remote(&self, session_id: &str) -> Result<String> {
49        let mut mutex = self.proteus.lock().await;
50        let proteus = mutex.as_mut().ok_or(Error::ProteusNotInitialized)?;
51        proteus.fingerprint_remote(session_id, &self.database).await
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use std::sync::Arc;
58
59    use core_crypto_keystore::{ConnectionType, Database, DatabaseKey};
60
61    use super::*;
62    use crate::test_utils::{x509::X509TestChain, *};
63
64    #[macro_rules_attribute::apply(smol_macros::test)]
65    async fn cc_can_init() {
66        #[cfg(not(target_os = "unknown"))]
67        let (path, db_file) = tmp_db_file();
68        #[cfg(target_os = "unknown")]
69        let (path, _) = tmp_db_file();
70        let db = Database::open(ConnectionType::Persistent(&path), &DatabaseKey::generate())
71            .await
72            .unwrap();
73
74        let cc = CoreCrypto::new(db);
75        let context = cc.new_transaction().await.unwrap();
76        assert!(context.proteus_init().await.is_ok());
77        assert!(context.proteus_new_prekey(1).await.is_ok());
78        context.finish().await.unwrap();
79        #[cfg(not(target_os = "unknown"))]
80        drop(db_file);
81    }
82
83    #[apply(all_cred_cipher)]
84    async fn cc_can_2_phase_init(case: TestContext) {
85        use wire_e2e_identity::pki_env::PkiEnvironment;
86
87        use crate::test_utils::DummyPkiEnvironmentHooks;
88
89        #[cfg(not(target_os = "unknown"))]
90        let (path, db_file) = tmp_db_file();
91        #[cfg(target_os = "unknown")]
92        let (path, _) = tmp_db_file();
93        let db = Database::open(ConnectionType::Persistent(&path), &DatabaseKey::generate())
94            .await
95            .unwrap();
96
97        let cc = CoreCrypto::new(db.clone());
98        let hooks = Arc::new(DummyPkiEnvironmentHooks);
99        let pki_env = PkiEnvironment::new(hooks, db).await.expect("creating pki environment");
100        cc.set_pki_environment(Some(Arc::new(pki_env))).await;
101        let transaction = cc.new_transaction().await.unwrap();
102        let x509_test_chain = X509TestChain::init_empty(case.signature_scheme());
103        x509_test_chain.register_with_central(&transaction).await;
104        assert!(transaction.proteus_init().await.is_ok());
105        // proteus is initialized, prekeys can be generated
106        assert!(transaction.proteus_new_prekey(1).await.is_ok());
107        // 👇 and so a unique 'client_id' can be fetched from wire-server
108        let transport = Arc::new(CoreCryptoTransportSuccessProvider::default());
109        let credential = case.generate_credential().await;
110        let session_id = credential.client_id().to_owned();
111        transaction.mls_init(session_id, transport).await.unwrap();
112        let credential_ref = transaction.add_credential(credential).await.unwrap();
113
114        // expect MLS to work
115        assert!(transaction.generate_key_package(&credential_ref, None).await.is_ok());
116
117        #[cfg(not(target_os = "unknown"))]
118        drop(db_file);
119    }
120}