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::{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(&path, &DatabaseKey::generate()).await.unwrap();
71
72        let cc = CoreCrypto::new(db);
73        let context = cc.new_transaction().await.unwrap();
74        assert!(context.proteus_init().await.is_ok());
75        assert!(context.proteus_new_prekey(1).await.is_ok());
76        context.finish().await.unwrap();
77        #[cfg(not(target_os = "unknown"))]
78        drop(db_file);
79    }
80
81    #[apply(all_cred_cipher)]
82    async fn cc_can_2_phase_init(case: TestContext) {
83        use wire_e2e_identity::pki_env::PkiEnvironment;
84
85        use crate::test_utils::DummyPkiEnvironmentHooks;
86
87        #[cfg(not(target_os = "unknown"))]
88        let (path, db_file) = tmp_db_file();
89        #[cfg(target_os = "unknown")]
90        let (path, _) = tmp_db_file();
91        let db = Database::open(&path, &DatabaseKey::generate()).await.unwrap();
92
93        let cc = CoreCrypto::new(db.clone());
94        let hooks = Arc::new(DummyPkiEnvironmentHooks);
95        let pki_env = PkiEnvironment::new(hooks, db).await.expect("creating pki environment");
96        cc.set_pki_environment(Some(Arc::new(pki_env))).await;
97        let transaction = cc.new_transaction().await.unwrap();
98        let x509_test_chain = X509TestChain::init_empty(case.signature_scheme());
99        x509_test_chain.register_with_central(&transaction).await;
100        assert!(transaction.proteus_init().await.is_ok());
101        // proteus is initialized, prekeys can be generated
102        assert!(transaction.proteus_new_prekey(1).await.is_ok());
103        // 👇 and so a unique 'client_id' can be fetched from wire-server
104        let transport = Arc::new(CoreCryptoTransportSuccessProvider::default());
105        let credential = case.generate_credential().await;
106        let session_id = credential.client_id().to_owned();
107        transaction.mls_init(session_id, transport).await.unwrap();
108        let credential_ref = transaction.add_credential(credential).await.unwrap();
109
110        // expect MLS to work
111        assert!(transaction.generate_key_package(&credential_ref, None).await.is_ok());
112
113        #[cfg(not(target_os = "unknown"))]
114        drop(db_file);
115    }
116}