core_crypto/transaction_context/e2e_identity/
mod.rs1pub(crate) mod conversation_state;
4pub mod enabled;
5mod error;
6mod init_certificates;
7mod rotate;
8mod stash;
9
10use std::collections::HashMap;
11
12use crate::{
13 RecursiveError,
14 mls::credential::x509::CertificatePrivateKey,
15 prelude::{CertificateBundle, ClientId, ClientIdentifier, E2eiEnrollment, MlsCiphersuite},
16};
17use openmls_traits::OpenMlsCryptoProvider as _;
18
19use super::TransactionContext;
20pub use crate::e2e_identity::E2eiDumpedPkiEnv;
21use crate::e2e_identity::NewCrlDistributionPoints;
22pub use error::{Error, Result};
23
24impl TransactionContext {
25 pub async fn e2ei_new_enrollment(
34 &self,
35 client_id: ClientId,
36 display_name: String,
37 handle: String,
38 team: Option<String>,
39 expiry_sec: u32,
40 ciphersuite: MlsCiphersuite,
41 ) -> Result<E2eiEnrollment> {
42 let signature_keypair = None; E2eiEnrollment::try_new(
44 client_id,
45 display_name,
46 handle,
47 team,
48 expiry_sec,
49 &self
50 .mls_provider()
51 .await
52 .map_err(RecursiveError::transaction("getting mls provider"))?,
53 ciphersuite,
54 signature_keypair,
55 #[cfg(not(target_family = "wasm"))]
56 None, )
58 .map_err(RecursiveError::e2e_identity("creating new enrollment"))
59 .map_err(Into::into)
60 }
61
62 pub async fn e2ei_mls_init_only(
65 &self,
66 enrollment: &mut E2eiEnrollment,
67 certificate_chain: String,
68 nb_init_key_packages: Option<usize>,
69 ) -> Result<NewCrlDistributionPoints> {
70 let sk = enrollment
71 .get_sign_key_for_mls()
72 .map_err(RecursiveError::e2e_identity("creating new enrollment"))?;
73 let cs = *enrollment.ciphersuite();
74 let certificate_chain = enrollment
75 .certificate_response(
76 certificate_chain,
77 self.mls_provider()
78 .await
79 .map_err(RecursiveError::transaction("getting mls provider"))?
80 .authentication_service()
81 .borrow()
82 .await
83 .as_ref()
84 .ok_or(Error::PkiEnvironmentUnset)?,
85 )
86 .await
87 .map_err(RecursiveError::e2e_identity("getting certificate response"))?;
88
89 let crl_new_distribution_points = self
90 .extract_dp_on_init(&certificate_chain[..])
91 .await
92 .map_err(RecursiveError::mls_credential("extracting dp on init"))?;
93
94 let private_key = CertificatePrivateKey {
95 value: sk,
96 signature_scheme: cs.signature_algorithm(),
97 };
98
99 let cert_bundle = CertificateBundle {
100 certificate_chain,
101 private_key,
102 };
103 let identifier = ClientIdentifier::X509(HashMap::from([(cs.signature_algorithm(), cert_bundle)]));
104 self.mls_init(identifier, vec![cs], nb_init_key_packages)
105 .await
106 .map_err(RecursiveError::mls("initializing mls"))?;
107 Ok(crl_new_distribution_points)
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use crate::e2e_identity::enrollment::test_utils as e2ei_utils;
114 use crate::mls::conversation::Conversation as _;
115 use crate::test_utils::x509::X509TestChain;
116 use crate::{prelude::*, test_utils::*};
117 use wasm_bindgen_test::*;
118
119 wasm_bindgen_test_configure!(run_in_browser);
120
121 #[apply(all_cred_cipher)]
122 #[wasm_bindgen_test]
123 async fn e2e_identity_should_work(case: TestCase) {
124 use e2ei_utils::E2EI_CLIENT_ID_URI;
125
126 run_test_wo_clients(case.clone(), move |mut cc| {
127 Box::pin(async move {
128 let x509_test_chain = X509TestChain::init_empty(case.signature_scheme());
129
130 let is_renewal = false;
131
132 let (mut enrollment, cert) = e2ei_utils::e2ei_enrollment(
133 &mut cc,
134 &case,
135 &x509_test_chain,
136 Some(E2EI_CLIENT_ID_URI),
137 is_renewal,
138 e2ei_utils::init_enrollment,
139 e2ei_utils::noop_restore,
140 )
141 .await
142 .unwrap();
143
144 cc.context
145 .e2ei_mls_init_only(&mut enrollment, cert, Some(INITIAL_KEYING_MATERIAL_COUNT))
146 .await
147 .unwrap();
148
149 let id = conversation_id();
151 cc.context
152 .new_conversation(&id, MlsCredentialType::X509, case.cfg.clone())
153 .await
154 .unwrap();
155 cc.context
156 .conversation(&id)
157 .await
158 .unwrap()
159 .encrypt_message("Hello e2e identity !")
160 .await
161 .unwrap();
162 assert_eq!(
163 cc.context
164 .conversation(&id)
165 .await
166 .unwrap()
167 .e2ei_conversation_state()
168 .await
169 .unwrap(),
170 E2eiConversationState::Verified
171 );
172 assert!(cc.context.e2ei_is_enabled(case.signature_scheme()).await.unwrap());
173 })
174 })
175 .await
176 }
177}