core_crypto/e2e_identity/
enabled.rs

1//! Utility for clients to get the current state of E2EI when the app resumes
2
3use super::Result;
4use crate::{
5    RecursiveError,
6    context::CentralContext,
7    mls,
8    prelude::{Client, MlsCentral, MlsCredentialType},
9};
10use openmls_traits::types::SignatureScheme;
11
12impl CentralContext {
13    /// See [MlsCentral::e2ei_is_enabled]
14    pub async fn e2ei_is_enabled(&self, signature_scheme: SignatureScheme) -> Result<bool> {
15        let client = self
16            .mls_client()
17            .await
18            .map_err(RecursiveError::root("getting mls client"))?;
19        client.e2ei_is_enabled(signature_scheme).await
20    }
21}
22
23impl MlsCentral {
24    /// Returns true when end-to-end-identity is enabled for the given SignatureScheme
25    pub async fn e2ei_is_enabled(&self, signature_scheme: SignatureScheme) -> Result<bool> {
26        self.mls_client.e2ei_is_enabled(signature_scheme).await
27    }
28}
29
30impl Client {
31    async fn e2ei_is_enabled(&self, signature_scheme: SignatureScheme) -> Result<bool> {
32        let x509_result = self
33            .find_most_recent_credential_bundle(signature_scheme, MlsCredentialType::X509)
34            .await;
35        match x509_result {
36            Err(mls::client::Error::CredentialNotFound(MlsCredentialType::X509)) => {
37                self.find_most_recent_credential_bundle(signature_scheme, MlsCredentialType::Basic)
38                    .await
39                    .map_err(RecursiveError::mls_client(
40                        "finding most recent basic credential bundle after searching for x509",
41                    ))?;
42                Ok(false)
43            }
44            Err(e) => Err(RecursiveError::mls_client("finding most recent x509 credential bundle")(e).into()),
45            Ok(_) => Ok(true),
46        }
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::{RecursiveError, e2e_identity::error::Error, mls, prelude::MlsCredentialType, test_utils::*};
53    use openmls_traits::types::SignatureScheme;
54    use wasm_bindgen_test::*;
55
56    wasm_bindgen_test_configure!(run_in_browser);
57
58    #[apply(all_cred_cipher)]
59    #[wasm_bindgen_test]
60    async fn should_be_false_when_basic_and_true_when_x509(case: TestCase) {
61        run_test_with_client_ids(case.clone(), ["alice"], move |[cc]| {
62            Box::pin(async move {
63                let e2ei_is_enabled = cc.context.e2ei_is_enabled(case.signature_scheme()).await.unwrap();
64                match case.credential_type {
65                    MlsCredentialType::Basic => assert!(!e2ei_is_enabled),
66                    MlsCredentialType::X509 => assert!(e2ei_is_enabled),
67                };
68            })
69        })
70        .await
71    }
72
73    #[apply(all_cred_cipher)]
74    #[wasm_bindgen_test]
75    async fn should_fail_when_no_client(case: TestCase) {
76        run_test_wo_clients(case.clone(), move |cc| {
77            Box::pin(async move {
78                assert!(matches!(
79                    cc.context.e2ei_is_enabled(case.signature_scheme()).await.unwrap_err(),
80                    Error::Recursive(RecursiveError::MlsClient {  source, .. })
81                    if matches!(*source, mls::client::Error::MlsNotInitialized)
82                ));
83            })
84        })
85        .await
86    }
87
88    #[apply(all_cred_cipher)]
89    #[wasm_bindgen_test]
90    async fn should_fail_when_no_credential_for_given_signature_scheme(case: TestCase) {
91        run_test_with_client_ids(case.clone(), ["alice"], move |[cc]| {
92            Box::pin(async move {
93                // just return something different from the signature scheme the MlsCentral was initialized with
94                let other_sc = match case.signature_scheme() {
95                    SignatureScheme::ED25519 => SignatureScheme::ECDSA_SECP256R1_SHA256,
96                    _ => SignatureScheme::ED25519,
97                };
98                assert!(matches!(
99                    cc.context.e2ei_is_enabled(other_sc).await.unwrap_err(),
100                    Error::Recursive(RecursiveError::MlsClient {  source, .. })
101                    if matches!(*source, mls::client::Error::CredentialNotFound(_))
102                ));
103            })
104        })
105        .await
106    }
107}