core_crypto/e2e_identity/
stash.rs1use openmls_traits::{random::OpenMlsRand, OpenMlsCryptoProvider};
2
3use crate::context::CentralContext;
4use crate::prelude::{CryptoError, CryptoResult, E2eiEnrollment};
5use core_crypto_keystore::CryptoKeystoreMls;
6use mls_crypto_provider::MlsCryptoProvider;
7
8pub(crate) type EnrollmentHandle = Vec<u8>;
11
12impl E2eiEnrollment {
13 pub(crate) async fn stash(self, backend: &MlsCryptoProvider) -> CryptoResult<EnrollmentHandle> {
14 const HANDLE_SIZE: usize = 32;
16
17 let content = serde_json::to_vec(&self)?;
18 let handle = backend.crypto().random_vec(HANDLE_SIZE).map_err(CryptoError::from)?;
19 backend
20 .key_store()
21 .save_e2ei_enrollment(&handle, &content)
22 .await
23 .map_err(CryptoError::from)?;
24 Ok(handle)
25 }
26
27 pub(crate) async fn stash_pop(backend: &MlsCryptoProvider, handle: EnrollmentHandle) -> CryptoResult<Self> {
28 let content = backend
29 .key_store()
30 .pop_e2ei_enrollment(&handle)
31 .await
32 .map_err(CryptoError::from)?;
33 Ok(serde_json::from_slice(&content)?)
34 }
35}
36
37impl CentralContext {
38 pub async fn e2ei_enrollment_stash(&self, enrollment: E2eiEnrollment) -> CryptoResult<EnrollmentHandle> {
47 enrollment.stash(&self.mls_provider().await?).await
48 }
49
50 pub async fn e2ei_enrollment_stash_pop(&self, handle: EnrollmentHandle) -> CryptoResult<E2eiEnrollment> {
55 E2eiEnrollment::stash_pop(&self.mls_provider().await?, handle).await
56 }
57}
58
59#[cfg(test)]
60mod tests {
61
62 use mls_crypto_provider::MlsCryptoProvider;
63 use wasm_bindgen_test::*;
64
65 use crate::{
66 e2e_identity::id::WireQualifiedClientId,
67 e2e_identity::tests::*,
68 prelude::{E2eiEnrollment, INITIAL_KEYING_MATERIAL_COUNT},
69 test_utils::{x509::X509TestChain, *},
70 };
71
72 wasm_bindgen_test_configure!(run_in_browser);
73
74 #[apply(all_cred_cipher)]
75 #[wasm_bindgen_test]
76 async fn stash_and_pop_should_not_abort_enrollment(case: TestCase) {
77 run_test_wo_clients(case.clone(), move |mut cc| {
78 Box::pin(async move {
79 let x509_test_chain = X509TestChain::init_empty(case.signature_scheme());
80
81 let is_renewal = false;
82 let (mut enrollment, cert) = e2ei_enrollment(
83 &mut cc,
84 &case,
85 &x509_test_chain,
86 Some(E2EI_CLIENT_ID_URI),
87 is_renewal,
88 init_enrollment,
89 |e, cc| {
90 Box::pin(async move {
91 let handle = cc.e2ei_enrollment_stash(e).await.unwrap();
92 cc.e2ei_enrollment_stash_pop(handle).await.unwrap()
93 })
94 },
95 )
96 .await
97 .unwrap();
98
99 assert!(cc
100 .context
101 .e2ei_mls_init_only(&mut enrollment, cert, Some(INITIAL_KEYING_MATERIAL_COUNT))
102 .await
103 .is_ok());
104 })
105 })
106 .await
107 }
108
109 #[apply(all_cred_cipher)]
111 #[wasm_bindgen_test]
112 async fn should_fail_when_restoring_invalid(case: TestCase) {
113 run_test_wo_clients(case.clone(), move |mut cc| {
114 Box::pin(async move {
115 let x509_test_chain = X509TestChain::init_empty(case.signature_scheme());
116
117 let is_renewal = false;
118 let result = e2ei_enrollment(
119 &mut cc,
120 &case,
121 &x509_test_chain,
122 Some(E2EI_CLIENT_ID_URI),
123 is_renewal,
124 init_enrollment,
125 move |e, _cc| {
126 Box::pin(async move {
127 let backend = MlsCryptoProvider::try_new_in_memory("new").await.unwrap();
129 backend.new_transaction().await.unwrap();
130 let client_id = e.client_id.parse::<WireQualifiedClientId>().unwrap();
131 E2eiEnrollment::try_new(
132 client_id.into(),
133 e.display_name,
134 e.handle,
135 e.team,
136 1,
137 &backend,
138 e.ciphersuite,
139 None,
140 #[cfg(not(target_family = "wasm"))]
141 None,
142 )
143 .unwrap()
144 })
145 },
146 )
147 .await;
148 assert!(result.is_err());
149 })
150 })
151 .await
152 }
153}