mls_crypto_provider/
lib.rs1#![doc = include_str!("../README.md")]
18
19pub use core_crypto_keystore::Connection as CryptoKeystore;
20
21mod crypto_provider;
22mod error;
23mod pki;
24
25pub use error::{MlsProviderError, MlsProviderResult};
26
27pub use crypto_provider::RustCrypto;
28
29pub use pki::{CertProfile, CertificateGenerationArgs, PkiKeypair};
30
31use crate::pki::PkiEnvironmentProvider;
32
33pub mod reexports {
34 pub use rand_core;
35}
36
37pub type RawEntropySeed = <rand_chacha::ChaCha20Rng as rand::SeedableRng>::Seed;
39
40#[derive(Debug, Clone, Default, PartialEq, Eq, zeroize::ZeroizeOnDrop)]
41#[repr(transparent)]
42pub struct EntropySeed(RawEntropySeed);
44
45impl EntropySeed {
46 pub const EXPECTED_LEN: usize = std::mem::size_of::<EntropySeed>() / std::mem::size_of::<u8>();
47
48 pub fn try_from_slice(data: &[u8]) -> MlsProviderResult<Self> {
49 if data.len() < Self::EXPECTED_LEN {
50 return Err(MlsProviderError::EntropySeedLengthError {
51 actual: data.len(),
52 expected: Self::EXPECTED_LEN,
53 });
54 }
55
56 let mut inner = RawEntropySeed::default();
57 inner.copy_from_slice(&data[..Self::EXPECTED_LEN]);
58
59 Ok(Self(inner))
60 }
61
62 pub fn from_raw(raw: RawEntropySeed) -> Self {
63 Self(raw)
64 }
65}
66
67impl std::ops::Deref for EntropySeed {
68 type Target = [u8];
69 fn deref(&self) -> &Self::Target {
70 &self.0
71 }
72}
73
74impl std::ops::DerefMut for EntropySeed {
75 fn deref_mut(&mut self) -> &mut Self::Target {
76 &mut self.0
77 }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct MlsCryptoProviderConfiguration<'a> {
82 pub db_path: &'a str,
84 pub identity_key: &'a str,
86 pub in_memory: bool,
88 pub entropy_seed: Option<EntropySeed>,
90}
91
92#[derive(Debug, Clone)]
93pub struct MlsCryptoProvider {
94 crypto: RustCrypto,
95 key_store: CryptoKeystore,
96 pki_env: PkiEnvironmentProvider,
97}
98
99impl MlsCryptoProvider {
100 pub async fn try_new_with_configuration(config: MlsCryptoProviderConfiguration<'_>) -> MlsProviderResult<Self> {
102 let crypto = config.entropy_seed.map(RustCrypto::new_with_seed).unwrap_or_default();
103 let key_store = if config.in_memory {
104 CryptoKeystore::open_in_memory_with_key("", config.identity_key).await?
105 } else {
106 CryptoKeystore::open_with_key(config.db_path, config.identity_key).await?
107 };
108 Ok(Self {
109 crypto,
110 key_store,
111 pki_env: PkiEnvironmentProvider::default(),
112 })
113 }
114
115 pub async fn try_new(db_path: impl AsRef<str>, identity_key: impl AsRef<str>) -> MlsProviderResult<Self> {
116 let crypto = RustCrypto::default();
117 let key_store = CryptoKeystore::open_with_key(db_path, identity_key.as_ref()).await?;
118 Ok(Self {
119 crypto,
120 key_store,
121 pki_env: PkiEnvironmentProvider::default(),
122 })
123 }
124
125 pub async fn try_new_in_memory(identity_key: impl AsRef<str>) -> MlsProviderResult<Self> {
126 let crypto = RustCrypto::default();
127 let key_store = CryptoKeystore::open_in_memory_with_key("", identity_key.as_ref()).await?;
128 Ok(Self {
129 crypto,
130 key_store,
131 pki_env: PkiEnvironmentProvider::default(),
132 })
133 }
134
135 pub fn new_with_store(key_store: CryptoKeystore, entropy_seed: Option<EntropySeed>) -> Self {
137 let crypto = entropy_seed.map(RustCrypto::new_with_seed).unwrap_or_default();
138 Self {
139 crypto,
140 key_store,
141 pki_env: PkiEnvironmentProvider::default(),
142 }
143 }
144
145 pub async fn new_transaction(&self) -> MlsProviderResult<()> {
148 self.key_store.new_transaction().await.map_err(Into::into)
149 }
150
151 pub async fn update_pki_env(
153 &self,
154 pki_env: wire_e2e_identity::prelude::x509::revocation::PkiEnvironment,
155 ) -> MlsProviderResult<()> {
156 self.pki_env.update_env(pki_env).await
157 }
158
159 pub async fn is_pki_env_setup(&self) -> bool {
161 self.pki_env.is_env_setup().await
162 }
163
164 pub fn reseed(&self, entropy_seed: Option<EntropySeed>) -> MlsProviderResult<()> {
168 self.crypto.reseed(entropy_seed)
169 }
170
171 pub async fn close(self) -> MlsProviderResult<()> {
175 Ok(self.key_store.close().await?)
176 }
177
178 pub async fn destroy_and_reset(self) -> MlsProviderResult<()> {
182 Ok(self.key_store.wipe().await?)
183 }
184
185 pub fn keystore(&self) -> CryptoKeystore {
187 self.key_store.clone()
188 }
189
190 pub fn unwrap_keystore(self) -> CryptoKeystore {
192 self.key_store
193 }
194}
195
196impl openmls_traits::OpenMlsCryptoProvider for MlsCryptoProvider {
197 type CryptoProvider = RustCrypto;
198 type RandProvider = RustCrypto;
199 type KeyStoreProvider = CryptoKeystore;
200 type AuthenticationServiceProvider = PkiEnvironmentProvider;
201
202 fn crypto(&self) -> &Self::CryptoProvider {
203 &self.crypto
204 }
205
206 fn rand(&self) -> &Self::RandProvider {
207 &self.crypto
208 }
209
210 fn key_store(&self) -> &Self::KeyStoreProvider {
211 &self.key_store
212 }
213
214 fn authentication_service(&self) -> &Self::AuthenticationServiceProvider {
215 &self.pki_env
216 }
217}