1#![doc = include_str!("../README.md")]
2
3pub use core_crypto_keystore::{Database, DatabaseKey};
4
5mod crypto_provider;
6mod error;
7mod pki;
8
9pub use crypto_provider::RustCrypto;
10pub use error::{MlsProviderError, MlsProviderResult};
11use openmls_traits::{
12 crypto::OpenMlsCrypto,
13 types::{
14 AeadType, Ciphersuite, CryptoError, ExporterSecret, HashType, HpkeCiphertext, HpkeConfig, HpkeKeyPair,
15 KemOutput, SignatureScheme,
16 },
17};
18pub use pki::{CertProfile, CertificateGenerationArgs, PkiKeypair};
19
20use crate::pki::PkiEnvironmentProvider;
21
22pub mod reexports {
23 pub use rand_core;
24}
25
26pub type RawEntropySeed = <rand_chacha::ChaCha20Rng as rand::SeedableRng>::Seed;
28
29#[derive(Debug, Clone, Default, PartialEq, Eq, zeroize::ZeroizeOnDrop)]
30#[repr(transparent)]
31pub struct EntropySeed(RawEntropySeed);
33
34impl EntropySeed {
35 pub const EXPECTED_LEN: usize = std::mem::size_of::<EntropySeed>() / std::mem::size_of::<u8>();
36
37 pub fn try_from_slice(data: &[u8]) -> MlsProviderResult<Self> {
38 if data.len() < Self::EXPECTED_LEN {
39 return Err(MlsProviderError::EntropySeedLengthError {
40 actual: data.len(),
41 expected: Self::EXPECTED_LEN,
42 });
43 }
44
45 let mut inner = RawEntropySeed::default();
46 inner.copy_from_slice(&data[..Self::EXPECTED_LEN]);
47
48 Ok(Self(inner))
49 }
50
51 pub fn from_raw(raw: RawEntropySeed) -> Self {
52 Self(raw)
53 }
54}
55
56impl std::ops::Deref for EntropySeed {
57 type Target = [u8];
58 fn deref(&self) -> &Self::Target {
59 &self.0
60 }
61}
62
63impl std::ops::DerefMut for EntropySeed {
64 fn deref_mut(&mut self) -> &mut Self::Target {
65 &mut self.0
66 }
67}
68
69#[derive(Debug, Clone)]
70pub struct MlsCryptoProvider {
71 crypto: RustCrypto,
72 key_store: Database,
73 pki_env: PkiEnvironmentProvider,
74}
75
76impl MlsCryptoProvider {
77 pub fn new(key_store: Database) -> Self {
83 Self {
84 key_store,
85 crypto: Default::default(),
86 pki_env: Default::default(),
87 }
88 }
89
90 pub async fn new_transaction(&self) -> MlsProviderResult<()> {
93 self.key_store.new_transaction().await.map_err(Into::into)
94 }
95
96 pub async fn update_pki_env(
98 &self,
99 pki_env: wire_e2e_identity::prelude::x509::revocation::PkiEnvironment,
100 ) -> MlsProviderResult<()> {
101 self.pki_env.update_env(pki_env).await
102 }
103
104 pub async fn is_pki_env_setup(&self) -> bool {
106 self.pki_env.is_env_setup().await
107 }
108
109 pub fn reseed(&self, entropy_seed: Option<EntropySeed>) -> MlsProviderResult<()> {
113 self.crypto.reseed(entropy_seed)
114 }
115
116 pub async fn close(&self) -> MlsProviderResult<()> {
120 self.key_store.close().await?;
121 Ok(())
122 }
123
124 pub fn keystore(&self) -> Database {
126 self.key_store.clone()
127 }
128
129 pub fn unwrap_keystore(self) -> Database {
131 self.key_store
132 }
133}
134
135impl openmls_traits::OpenMlsCryptoProvider for MlsCryptoProvider {
136 type CryptoProvider = RustCrypto;
137 type RandProvider = RustCrypto;
138 type KeyStoreProvider = Database;
139 type AuthenticationServiceProvider = PkiEnvironmentProvider;
140
141 fn crypto(&self) -> &Self::CryptoProvider {
142 &self.crypto
143 }
144
145 fn rand(&self) -> &Self::RandProvider {
146 &self.crypto
147 }
148
149 fn key_store(&self) -> &Self::KeyStoreProvider {
150 &self.key_store
151 }
152
153 fn authentication_service(&self) -> &Self::AuthenticationServiceProvider {
154 &self.pki_env
155 }
156}
157
158impl OpenMlsCrypto for &MlsCryptoProvider {
160 fn supports(&self, ciphersuite: Ciphersuite) -> Result<(), CryptoError> {
161 self.crypto.supports(ciphersuite)
162 }
163
164 fn supported_ciphersuites(&self) -> Vec<Ciphersuite> {
165 self.crypto.supported_ciphersuites()
166 }
167
168 fn hkdf_extract(
169 &self,
170 hash_type: HashType,
171 salt: &[u8],
172 ikm: &[u8],
173 ) -> Result<tls_codec::SecretVLBytes, CryptoError> {
174 self.crypto.hkdf_extract(hash_type, salt, ikm)
175 }
176
177 fn hkdf_expand(
178 &self,
179 hash_type: HashType,
180 prk: &[u8],
181 info: &[u8],
182 okm_len: usize,
183 ) -> Result<tls_codec::SecretVLBytes, CryptoError> {
184 self.crypto.hkdf_expand(hash_type, prk, info, okm_len)
185 }
186
187 fn hash(&self, hash_type: HashType, data: &[u8]) -> Result<Vec<u8>, CryptoError> {
188 self.crypto.hash(hash_type, data)
189 }
190
191 fn aead_encrypt(
192 &self,
193 alg: AeadType,
194 key: &[u8],
195 data: &[u8],
196 nonce: &[u8],
197 aad: &[u8],
198 ) -> Result<Vec<u8>, CryptoError> {
199 self.crypto.aead_encrypt(alg, key, data, nonce, aad)
200 }
201
202 fn aead_decrypt(
203 &self,
204 alg: AeadType,
205 key: &[u8],
206 ct_tag: &[u8],
207 nonce: &[u8],
208 aad: &[u8],
209 ) -> Result<Vec<u8>, CryptoError> {
210 self.crypto.aead_decrypt(alg, key, ct_tag, nonce, aad)
211 }
212
213 fn signature_key_gen(&self, alg: SignatureScheme) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
214 self.crypto.signature_key_gen(alg)
215 }
216
217 fn signature_public_key_len(&self, alg: SignatureScheme) -> usize {
218 self.crypto.signature_public_key_len(alg)
219 }
220
221 fn validate_signature_key(&self, alg: SignatureScheme, key: &[u8]) -> Result<(), CryptoError> {
222 self.crypto.validate_signature_key(alg, key)
223 }
224
225 fn verify_signature(
226 &self,
227 alg: SignatureScheme,
228 data: &[u8],
229 pk: &[u8],
230 signature: &[u8],
231 ) -> Result<(), CryptoError> {
232 self.crypto.verify_signature(alg, data, pk, signature)
233 }
234
235 fn sign(&self, alg: SignatureScheme, data: &[u8], key: &[u8]) -> Result<Vec<u8>, CryptoError> {
236 self.crypto.sign(alg, data, key)
237 }
238
239 fn hpke_seal(
240 &self,
241 config: HpkeConfig,
242 pk_r: &[u8],
243 info: &[u8],
244 aad: &[u8],
245 ptxt: &[u8],
246 ) -> Result<HpkeCiphertext, CryptoError> {
247 self.crypto.hpke_seal(config, pk_r, info, aad, ptxt)
248 }
249
250 fn hpke_open(
251 &self,
252 config: HpkeConfig,
253 input: &HpkeCiphertext,
254 sk_r: &[u8],
255 info: &[u8],
256 aad: &[u8],
257 ) -> Result<Vec<u8>, CryptoError> {
258 self.crypto.hpke_open(config, input, sk_r, info, aad)
259 }
260
261 fn hpke_setup_sender_and_export(
262 &self,
263 config: HpkeConfig,
264 pk_r: &[u8],
265 info: &[u8],
266 exporter_context: &[u8],
267 exporter_length: usize,
268 ) -> Result<(KemOutput, ExporterSecret), CryptoError> {
269 self.crypto
270 .hpke_setup_sender_and_export(config, pk_r, info, exporter_context, exporter_length)
271 }
272
273 fn hpke_setup_receiver_and_export(
274 &self,
275 config: HpkeConfig,
276 enc: &[u8],
277 sk_r: &[u8],
278 info: &[u8],
279 exporter_context: &[u8],
280 exporter_length: usize,
281 ) -> Result<ExporterSecret, CryptoError> {
282 self.crypto
283 .hpke_setup_receiver_and_export(config, enc, sk_r, info, exporter_context, exporter_length)
284 }
285
286 fn derive_hpke_keypair(&self, config: HpkeConfig, ikm: &[u8]) -> Result<HpkeKeyPair, CryptoError> {
287 self.crypto.derive_hpke_keypair(config, ikm)
288 }
289}