1use std::sync::{Arc, LazyLock, RwLock, RwLockWriteGuard};
2
3use aes_gcm::{
4 Aes128Gcm, Aes256Gcm, KeyInit,
5 aead::{Aead, Payload},
6};
7use chacha20poly1305::ChaCha20Poly1305;
8use hkdf::Hkdf;
9use openmls_traits::{
10 crypto::OpenMlsCrypto,
11 random::OpenMlsRand,
12 types::{
13 self, AeadType, Ciphersuite, CryptoError, ExporterSecret, HashType, HpkeAeadType, HpkeConfig, HpkeKdfType,
14 HpkeKemType, SignatureScheme,
15 },
16};
17use rand_core::{RngCore, SeedableRng};
18use sha2::{Digest, Sha256, Sha384, Sha512};
19use signature::digest::typenum::Unsigned;
20use tls_codec::SecretVLBytes;
21
22use super::{EntropySeed, MlsProviderError};
23
24pub(crate) static CRYPTO: LazyLock<Arc<RustCrypto>> = LazyLock::new(|| Arc::new(RustCrypto::default()));
27
28#[derive(Debug, Clone)]
34pub struct RustCrypto {
35 pub(crate) rng: Arc<RwLock<rand_chacha::ChaCha20Rng>>,
36}
37
38impl Default for RustCrypto {
39 fn default() -> Self {
40 Self {
41 rng: Arc::new(rand_chacha::ChaCha20Rng::from_entropy().into()),
42 }
43 }
44}
45
46#[inline]
47fn normalize_p521_secret_key(sk: &[u8]) -> zeroize::Zeroizing<[u8; 66]> {
48 let mut sk_buf = zeroize::Zeroizing::new([0u8; 66]);
49 sk_buf[66 - sk.len()..].copy_from_slice(sk);
50 sk_buf
51}
52
53impl RustCrypto {
54 #[expect(unused)]
56 pub(crate) fn new_with_seed(seed: EntropySeed) -> Self {
57 Self {
58 rng: Arc::new(rand_chacha::ChaCha20Rng::from_seed(seed.0).into()),
59 }
60 }
61
62 pub(crate) fn reseed(&self, seed: Option<EntropySeed>) -> Result<(), MlsProviderError> {
63 let mut val = self.rng.write().map_err(|_| MlsProviderError::RngLockPoison)?;
64 *val = rand_chacha::ChaCha20Rng::from_seed(seed.unwrap_or_default().0);
65 Ok(())
66 }
67
68 #[expect(unused)]
71 pub(crate) fn normalize_p521_secret_key(sk: &[u8]) -> zeroize::Zeroizing<[u8; 66]> {
72 normalize_p521_secret_key(sk)
73 }
74
75 pub(crate) fn normalize_ed25519_key(key: &[u8]) -> Result<ed25519_dalek::SigningKey, CryptoError> {
76 let k = match key.len() {
77 ed25519_dalek::KEYPAIR_LENGTH => {
79 let mut sk = zeroize::Zeroizing::new([0u8; ed25519_dalek::KEYPAIR_LENGTH]);
80 sk.copy_from_slice(key);
81 ed25519_dalek::SigningKey::from_keypair_bytes(&sk).map_err(|_| CryptoError::CryptoLibraryError)?
82 }
83 ed25519_dalek::SECRET_KEY_LENGTH => {
84 let mut sk = zeroize::Zeroizing::new([0u8; ed25519_dalek::SECRET_KEY_LENGTH]);
85 sk.copy_from_slice(key);
86 ed25519_dalek::SigningKey::from_bytes(&sk)
87 }
88 _ => return Err(CryptoError::CryptoLibraryError),
89 };
90 Ok(k)
91 }
92}
93
94impl OpenMlsCrypto for RustCrypto {
95 fn signature_public_key_len(&self, signature_scheme: SignatureScheme) -> usize {
96 match signature_scheme {
97 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
98 <p256::NistP256 as p256::elliptic_curve::Curve>::FieldBytesSize::to_usize()
99 }
100 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
101 <p384::NistP384 as p384::elliptic_curve::Curve>::FieldBytesSize::to_usize()
102 }
103 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
104 <p521::NistP521 as p521::elliptic_curve::Curve>::FieldBytesSize::to_usize()
105 }
106 SignatureScheme::ED25519 => ed25519_dalek::PUBLIC_KEY_LENGTH,
107 SignatureScheme::ED448 => 57,
108 }
109 }
110
111 fn supports(&self, ciphersuite: Ciphersuite) -> Result<(), CryptoError> {
112 match ciphersuite {
113 Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
114 | Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519
115 | Ciphersuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256
116 | Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384
117 | Ciphersuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521 => Ok(()),
118 _ => Err(CryptoError::UnsupportedCiphersuite),
119 }
120 }
121
122 fn supported_ciphersuites(&self) -> Vec<Ciphersuite> {
123 vec![
124 Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519,
125 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
126 Ciphersuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256,
127 Ciphersuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384,
128 Ciphersuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521,
129 ]
130 }
131
132 fn hkdf_extract(&self, hash_type: HashType, salt: &[u8], ikm: &[u8]) -> Result<SecretVLBytes, CryptoError> {
133 match hash_type {
134 HashType::Sha2_256 => Ok(Hkdf::<Sha256>::extract(Some(salt), ikm).0.as_slice().into()),
135 HashType::Sha2_384 => Ok(Hkdf::<Sha384>::extract(Some(salt), ikm).0.as_slice().into()),
136 HashType::Sha2_512 => Ok(Hkdf::<Sha512>::extract(Some(salt), ikm).0.as_slice().into()),
137 }
138 }
139
140 fn hkdf_expand(
141 &self,
142 hash_type: HashType,
143 prk: &[u8],
144 info: &[u8],
145 okm_len: usize,
146 ) -> Result<SecretVLBytes, CryptoError> {
147 match hash_type {
148 HashType::Sha2_256 => {
149 let hkdf = Hkdf::<Sha256>::from_prk(prk).map_err(|_| CryptoError::HkdfOutputLengthInvalid)?;
150
151 let mut okm = vec![0u8; okm_len];
152 hkdf.expand(info, &mut okm)
153 .map_err(|_| CryptoError::HkdfOutputLengthInvalid)?;
154
155 Ok(okm.into())
156 }
157 HashType::Sha2_384 => {
158 let hkdf = Hkdf::<Sha384>::from_prk(prk).map_err(|_| CryptoError::HkdfOutputLengthInvalid)?;
159
160 let mut okm = vec![0u8; okm_len];
161 hkdf.expand(info, &mut okm)
162 .map_err(|_| CryptoError::HkdfOutputLengthInvalid)?;
163
164 Ok(okm.into())
165 }
166 HashType::Sha2_512 => {
167 let hkdf = Hkdf::<Sha512>::from_prk(prk).map_err(|_| CryptoError::HkdfOutputLengthInvalid)?;
168
169 let mut okm = vec![0u8; okm_len];
170 hkdf.expand(info, &mut okm)
171 .map_err(|_| CryptoError::HkdfOutputLengthInvalid)?;
172
173 Ok(okm.into())
174 }
175 }
176 }
177
178 fn hash(&self, hash_type: HashType, data: &[u8]) -> Result<Vec<u8>, CryptoError> {
179 match hash_type {
180 HashType::Sha2_256 => Ok(Sha256::digest(data).as_slice().into()),
181 HashType::Sha2_384 => Ok(Sha384::digest(data).as_slice().into()),
182 HashType::Sha2_512 => Ok(Sha512::digest(data).as_slice().into()),
183 }
184 }
185
186 fn aead_encrypt(
187 &self,
188 alg: AeadType,
189 key: &[u8],
190 data: &[u8],
191 nonce: &[u8],
192 aad: &[u8],
193 ) -> Result<Vec<u8>, CryptoError> {
194 match alg {
195 AeadType::Aes128Gcm => {
196 let aes = Aes128Gcm::new_from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
197
198 aes.encrypt(nonce.into(), Payload { msg: data, aad })
199 .map(|r| r.as_slice().into())
200 .map_err(|_| CryptoError::CryptoLibraryError)
201 }
202 AeadType::Aes256Gcm => {
203 let aes = Aes256Gcm::new_from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
204
205 aes.encrypt(nonce.into(), Payload { msg: data, aad })
206 .map(|r| r.as_slice().into())
207 .map_err(|_| CryptoError::CryptoLibraryError)
208 }
209 AeadType::ChaCha20Poly1305 => {
210 let chacha_poly = ChaCha20Poly1305::new_from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
211
212 chacha_poly
213 .encrypt(nonce.into(), Payload { msg: data, aad })
214 .map(|r| r.as_slice().into())
215 .map_err(|_| CryptoError::CryptoLibraryError)
216 }
217 }
218 }
219
220 fn aead_decrypt(
221 &self,
222 alg: AeadType,
223 key: &[u8],
224 ct_tag: &[u8],
225 nonce: &[u8],
226 aad: &[u8],
227 ) -> Result<Vec<u8>, CryptoError> {
228 match alg {
229 AeadType::Aes128Gcm => {
230 let aes = Aes128Gcm::new_from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
231 aes.decrypt(nonce.into(), Payload { msg: ct_tag, aad })
232 .map(|r| r.as_slice().into())
233 .map_err(|_| CryptoError::AeadDecryptionError)
234 }
235 AeadType::Aes256Gcm => {
236 let aes = Aes256Gcm::new_from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
237 aes.decrypt(nonce.into(), Payload { msg: ct_tag, aad })
238 .map(|r| r.as_slice().into())
239 .map_err(|_| CryptoError::AeadDecryptionError)
240 }
241 AeadType::ChaCha20Poly1305 => {
242 let chacha_poly = ChaCha20Poly1305::new_from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
243 chacha_poly
244 .decrypt(nonce.into(), Payload { msg: ct_tag, aad })
245 .map(|r| r.as_slice().into())
246 .map_err(|_| CryptoError::AeadDecryptionError)
247 }
248 }
249 }
250
251 fn signature_key_gen(&self, alg: SignatureScheme) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
253 let mut rng = self.rng.write().map_err(|_| CryptoError::InsufficientRandomness)?;
254
255 match alg {
256 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
257 let sk = p256::ecdsa::SigningKey::random(&mut *rng);
258 let pk = sk.verifying_key().to_sec1_bytes().to_vec();
259 Ok((sk.to_bytes().to_vec(), pk))
260 }
261 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
262 let sk = p384::ecdsa::SigningKey::random(&mut *rng);
263 let pk = sk.verifying_key().to_sec1_bytes().to_vec();
264 Ok((sk.to_bytes().to_vec(), pk))
265 }
266 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
267 let sk = p521::ecdsa::SigningKey::random(&mut *rng);
268 let pk = p521::ecdsa::VerifyingKey::from(&sk)
269 .to_encoded_point(false)
270 .to_bytes()
271 .into();
272 Ok((sk.to_bytes().to_vec(), pk))
273 }
274 SignatureScheme::ED25519 => {
275 let k = ed25519_dalek::SigningKey::generate(&mut *rng);
276 let pk = k.verifying_key();
277 Ok((k.to_bytes().into(), pk.to_bytes().into()))
278 }
279 _ => Err(CryptoError::UnsupportedSignatureScheme),
280 }
281 }
282
283 fn validate_signature_key(&self, alg: SignatureScheme, key: &[u8]) -> Result<(), CryptoError> {
284 match alg {
285 SignatureScheme::ED25519 => {
286 ed25519_dalek::VerifyingKey::try_from(key).map_err(|_| CryptoError::InvalidKey)?;
287 }
288 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
289 p256::ecdsa::VerifyingKey::try_from(key).map_err(|_| CryptoError::InvalidKey)?;
290 }
291 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
292 p384::ecdsa::VerifyingKey::try_from(key).map_err(|_| CryptoError::InvalidKey)?;
293 }
294 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
295 p521::ecdsa::VerifyingKey::from_sec1_bytes(key).map_err(|_| CryptoError::InvalidKey)?;
296 }
297 SignatureScheme::ED448 => {
298 return Err(CryptoError::UnsupportedSignatureScheme);
299 }
300 }
301 Ok(())
302 }
303
304 fn verify_signature(
305 &self,
306 alg: SignatureScheme,
307 data: &[u8],
308 pk: &[u8],
309 signature: &[u8],
310 ) -> Result<(), CryptoError> {
311 use signature::Verifier as _;
312 match alg {
313 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
314 let k = p256::ecdsa::VerifyingKey::from_sec1_bytes(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
315
316 let signature =
317 p256::ecdsa::DerSignature::from_bytes(signature).map_err(|_| CryptoError::InvalidSignature)?;
318
319 k.verify(data, &signature).map_err(|_| CryptoError::InvalidSignature)
320 }
321 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
322 let k = p384::ecdsa::VerifyingKey::from_sec1_bytes(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
323
324 let signature =
325 p384::ecdsa::DerSignature::from_bytes(signature).map_err(|_| CryptoError::InvalidSignature)?;
326
327 k.verify(data, &signature).map_err(|_| CryptoError::InvalidSignature)
328 }
329 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
330 let k = p521::ecdsa::VerifyingKey::from_sec1_bytes(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
331
332 let signature =
333 p521::ecdsa::Signature::from_der(signature).map_err(|_| CryptoError::InvalidSignature)?;
334
335 k.verify(data, &signature).map_err(|_| CryptoError::InvalidSignature)
336 }
337 SignatureScheme::ED25519 => {
338 let k = ed25519_dalek::VerifyingKey::try_from(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
339
340 let sig = ed25519_dalek::Signature::from_slice(signature).map_err(|_| CryptoError::InvalidSignature)?;
341
342 k.verify_strict(data, &sig).map_err(|_| CryptoError::InvalidSignature)
343 }
344 _ => Err(CryptoError::UnsupportedSignatureScheme),
345 }
346 }
347
348 fn sign(&self, alg: SignatureScheme, data: &[u8], key: &[u8]) -> Result<Vec<u8>, CryptoError> {
349 use signature::Signer as _;
350
351 match alg {
352 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
353 let k = p256::ecdsa::SigningKey::from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
354 let signature: p256::ecdsa::DerSignature =
355 k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?;
356 Ok(signature.to_bytes().into())
357 }
358 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
359 let k = p384::ecdsa::SigningKey::from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
360 let signature: p384::ecdsa::DerSignature =
361 k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?;
362 Ok(signature.to_bytes().into())
363 }
364 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
365 let k = p521::ecdsa::SigningKey::from_slice(&*normalize_p521_secret_key(key))
366 .map_err(|_| CryptoError::CryptoLibraryError)?;
367 let signature: p521::ecdsa::DerSignature =
368 k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?.to_der();
369 Ok(signature.to_bytes().into())
370 }
371 SignatureScheme::ED25519 => {
372 let k = Self::normalize_ed25519_key(key)?;
373 let signature = k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?;
374 Ok(signature.to_bytes().into())
375 }
376 _ => Err(CryptoError::UnsupportedSignatureScheme),
377 }
378 }
379
380 fn hpke_seal(
381 &self,
382 config: HpkeConfig,
383 pk_r: &[u8],
384 info: &[u8],
385 aad: &[u8],
386 ptxt: &[u8],
387 ) -> Result<types::HpkeCiphertext, CryptoError> {
388 let mut rng = self.rng.write().map_err(|_| CryptoError::InsufficientRandomness)?;
389
390 match config {
391 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
392 hpke_core::hpke_seal::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
393 pk_r, info, aad, ptxt, &mut *rng,
394 )
395 }
396 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
397 hpke_core::hpke_seal::<hpke::aead::ChaCha20Poly1305, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
398 pk_r, info, aad, ptxt, &mut *rng,
399 )
400 }
401 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
402 hpke_core::hpke_seal::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::DhP256HkdfSha256>(
403 pk_r, info, aad, ptxt, &mut *rng,
404 )
405 }
406 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
407 hpke_core::hpke_seal::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha384, hpke::kem::DhP384HkdfSha384>(
408 pk_r, info, aad, ptxt, &mut *rng,
409 )
410 }
411 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
412 hpke_core::hpke_seal::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha512, hpke::kem::DhP521HkdfSha512>(
413 pk_r, info, aad, ptxt, &mut *rng,
414 )
415 }
416 _ => Err(CryptoError::UnsupportedKem),
417 }
418 }
419
420 fn hpke_open(
421 &self,
422 config: HpkeConfig,
423 input: &types::HpkeCiphertext,
424 sk_r: &[u8],
425 info: &[u8],
426 aad: &[u8],
427 ) -> Result<Vec<u8>, CryptoError> {
428 let plaintext = match config {
429 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
430 hpke_core::hpke_open::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
431 sk_r,
432 input.kem_output.as_slice(),
433 info,
434 aad,
435 input.ciphertext.as_slice(),
436 )?
437 }
438 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
439 hpke_core::hpke_open::<hpke::aead::ChaCha20Poly1305, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
440 sk_r,
441 input.kem_output.as_slice(),
442 info,
443 aad,
444 input.ciphertext.as_slice(),
445 )?
446 }
447 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
448 hpke_core::hpke_open::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::DhP256HkdfSha256>(
449 sk_r,
450 input.kem_output.as_slice(),
451 info,
452 aad,
453 input.ciphertext.as_slice(),
454 )?
455 }
456 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
457 hpke_core::hpke_open::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha384, hpke::kem::DhP384HkdfSha384>(
458 sk_r,
459 input.kem_output.as_slice(),
460 info,
461 aad,
462 input.ciphertext.as_slice(),
463 )?
464 }
465 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
466 hpke_core::hpke_open::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha512, hpke::kem::DhP521HkdfSha512>(
467 sk_r,
468 input.kem_output.as_slice(),
469 info,
470 aad,
471 input.ciphertext.as_slice(),
472 )?
473 }
474 _ => return Err(CryptoError::UnsupportedKem),
475 };
476
477 Ok(plaintext)
478 }
479
480 fn hpke_setup_sender_and_export(
481 &self,
482 config: HpkeConfig,
483 pk_r: &[u8],
484 info: &[u8],
485 exporter_context: &[u8],
486 exporter_length: usize,
487 ) -> Result<(Vec<u8>, ExporterSecret), CryptoError> {
488 let mut rng = self.rng.write().map_err(|_| CryptoError::InsufficientRandomness)?;
489
490 let (kem_output, export) =
491 match config {
492 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
493 hpke_core::hpke_export_tx::<
494 hpke::aead::AesGcm128,
495 hpke::kdf::HkdfSha256,
496 hpke::kem::X25519HkdfSha256,
497 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
498 }
499 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
500 hpke_core::hpke_export_tx::<
501 hpke::aead::ChaCha20Poly1305,
502 hpke::kdf::HkdfSha256,
503 hpke::kem::X25519HkdfSha256,
504 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
505 }
506 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
507 hpke_core::hpke_export_tx::<
508 hpke::aead::AesGcm128,
509 hpke::kdf::HkdfSha256,
510 hpke::kem::DhP256HkdfSha256,
511 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
512 }
513 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
514 hpke_core::hpke_export_tx::<
515 hpke::aead::AesGcm256,
516 hpke::kdf::HkdfSha384,
517 hpke::kem::DhP384HkdfSha384,
518 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
519 }
520 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
521 hpke_core::hpke_export_tx::<
522 hpke::aead::AesGcm256,
523 hpke::kdf::HkdfSha512,
524 hpke::kem::DhP521HkdfSha512,
525 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
526 }
527 _ => return Err(CryptoError::UnsupportedKem),
528 };
529
530 debug_assert_eq!(export.len(), exporter_length);
531
532 Ok((kem_output, export.into()))
533 }
534
535 fn hpke_setup_receiver_and_export(
536 &self,
537 config: HpkeConfig,
538 enc: &[u8],
539 sk_r: &[u8],
540 info: &[u8],
541 exporter_context: &[u8],
542 exporter_length: usize,
543 ) -> Result<ExporterSecret, CryptoError> {
544 let export =
545 match config {
546 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
547 hpke_core::hpke_export_rx::<
548 hpke::aead::AesGcm128,
549 hpke::kdf::HkdfSha256,
550 hpke::kem::X25519HkdfSha256,
551 >(enc, sk_r, info, exporter_context, exporter_length)?
552 }
553 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
554 hpke_core::hpke_export_rx::<
555 hpke::aead::ChaCha20Poly1305,
556 hpke::kdf::HkdfSha256,
557 hpke::kem::X25519HkdfSha256,
558 >(enc, sk_r, info, exporter_context, exporter_length)?
559 }
560 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
561 hpke_core::hpke_export_rx::<
562 hpke::aead::AesGcm128,
563 hpke::kdf::HkdfSha256,
564 hpke::kem::DhP256HkdfSha256,
565 >(enc, sk_r, info, exporter_context, exporter_length)?
566 }
567 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
568 hpke_core::hpke_export_rx::<
569 hpke::aead::AesGcm256,
570 hpke::kdf::HkdfSha384,
571 hpke::kem::DhP384HkdfSha384,
572 >(enc, sk_r, info, exporter_context, exporter_length)?
573 }
574 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
575 hpke_core::hpke_export_rx::<
576 hpke::aead::AesGcm256,
577 hpke::kdf::HkdfSha512,
578 hpke::kem::DhP521HkdfSha512,
579 >(enc, sk_r, info, exporter_context, exporter_length)?
580 }
581 _ => return Err(CryptoError::UnsupportedKem),
582 };
583
584 debug_assert_eq!(export.len(), exporter_length);
585
586 Ok(export.into())
587 }
588
589 fn derive_hpke_keypair(&self, config: HpkeConfig, ikm: &[u8]) -> Result<types::HpkeKeyPair, CryptoError> {
590 match config.0 {
591 HpkeKemType::DhKemP256 => hpke_core::hpke_derive_keypair::<hpke::kem::DhP256HkdfSha256>(ikm),
592 HpkeKemType::DhKemP384 => hpke_core::hpke_derive_keypair::<hpke::kem::DhP384HkdfSha384>(ikm),
593 HpkeKemType::DhKemP521 => hpke_core::hpke_derive_keypair::<hpke::kem::DhP521HkdfSha512>(ikm),
594 HpkeKemType::DhKem25519 => hpke_core::hpke_derive_keypair::<hpke::kem::X25519HkdfSha256>(ikm),
595 _ => Err(CryptoError::UnsupportedKem),
596 }
597 }
598}
599
600mod hpke_core {
601 use openmls_traits::types::{CryptoError, HpkeCiphertext, HpkeKeyPair};
602
603 pub(crate) fn hpke_open<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
604 private_key: &[u8],
605 kem_output: &[u8],
606 info: &[u8],
607 aad: &[u8],
608 ciphertext: &[u8],
609 ) -> Result<Vec<u8>, CryptoError> {
610 use hpke::{Deserializable as _, Serializable as _};
611 let encapped_key = Kem::EncappedKey::from_bytes(kem_output).map_err(|_| CryptoError::HpkeDecryptionError)?;
612 let sk_len = Kem::PrivateKey::size();
614 let mut sk_buf = zeroize::Zeroizing::new(Vec::with_capacity(sk_len));
615 if private_key.len() < sk_len {
616 for _ in 0..(sk_len - private_key.len()) {
617 sk_buf.push(0x00);
618 }
619 }
620 sk_buf.extend_from_slice(private_key);
621 let key = Kem::PrivateKey::from_bytes(&sk_buf).map_err(|_| CryptoError::HpkeDecryptionError)?;
622 let plaintext =
623 hpke::single_shot_open::<Aead, Kdf, Kem>(&hpke::OpModeR::Base, &key, &encapped_key, info, ciphertext, aad)
624 .map_err(|_| CryptoError::HpkeDecryptionError)?;
625
626 Ok(plaintext)
627 }
628
629 pub(crate) fn hpke_seal<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
630 public_key: &[u8],
631 info: &[u8],
632 aad: &[u8],
633 plaintext: &[u8],
634 csprng: &mut impl rand_core::CryptoRngCore,
635 ) -> Result<HpkeCiphertext, CryptoError> {
636 use hpke::{Deserializable as _, Serializable as _};
637 let key = Kem::PublicKey::from_bytes(public_key).map_err(|_| CryptoError::HpkeEncryptionError)?;
638 let (encapped, ciphertext) =
639 hpke::single_shot_seal::<Aead, Kdf, Kem, _>(&hpke::OpModeS::Base, &key, info, plaintext, aad, csprng)
640 .map_err(|_| CryptoError::HpkeEncryptionError)?;
641
642 Ok(HpkeCiphertext {
643 kem_output: encapped.to_bytes().to_vec().into(),
644 ciphertext: ciphertext.into(),
645 })
646 }
647
648 #[allow(dead_code)]
649 pub(crate) fn hpke_gen_keypair<Kem: hpke::Kem>(
650 csprng: &mut impl rand_core::CryptoRngCore,
651 ) -> Result<HpkeKeyPair, CryptoError> {
652 use hpke::Serializable as _;
653 let (sk, pk) = Kem::gen_keypair(csprng);
654 let (private, public) = (sk.to_bytes().to_vec().into(), pk.to_bytes().to_vec());
655
656 Ok(HpkeKeyPair { private, public })
657 }
658
659 pub(crate) fn hpke_derive_keypair<Kem: hpke::Kem>(ikm: &[u8]) -> Result<HpkeKeyPair, CryptoError> {
660 use hpke::Serializable as _;
661 let (sk, pk) = Kem::derive_keypair(ikm);
662 let (private, public) = (sk.to_bytes().to_vec().into(), pk.to_bytes().to_vec());
663
664 Ok(HpkeKeyPair { private, public })
665 }
666
667 pub(crate) fn hpke_export_rx<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
668 encapped_key: &[u8],
669 rx_private_key: &[u8],
670 info: &[u8],
671 export_info: &[u8],
672 export_len: usize,
673 ) -> Result<Vec<u8>, CryptoError> {
674 use hpke::Deserializable as _;
675 let key = Kem::PrivateKey::from_bytes(rx_private_key).map_err(|_| CryptoError::ReceiverSetupError)?;
676 let encapped_key = Kem::EncappedKey::from_bytes(encapped_key).map_err(|_| CryptoError::ReceiverSetupError)?;
677 let ctx = hpke::setup_receiver::<Aead, Kdf, Kem>(&hpke::OpModeR::Base, &key, &encapped_key, info)
678 .map_err(|_| CryptoError::ReceiverSetupError)?;
679
680 let mut export = vec![0u8; export_len];
681
682 ctx.export(export_info, &mut export)
683 .map_err(|_| CryptoError::ExporterError)?;
684
685 Ok(export)
686 }
687
688 pub(crate) fn hpke_export_tx<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
689 tx_public_key: &[u8],
690 info: &[u8],
691 export_info: &[u8],
692 export_len: usize,
693 csprng: &mut impl rand_core::CryptoRngCore,
694 ) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
695 use hpke::{Deserializable as _, Serializable as _};
696 let key = Kem::PublicKey::from_bytes(tx_public_key).map_err(|_| CryptoError::SenderSetupError)?;
697 let (kem_output, ctx) = hpke::setup_sender::<Aead, Kdf, Kem, _>(&hpke::OpModeS::Base, &key, info, csprng)
698 .map_err(|_| CryptoError::SenderSetupError)?;
699
700 let mut export = vec![0u8; export_len];
701
702 ctx.export(export_info, &mut export)
703 .map_err(|_| CryptoError::ExporterError)?;
704
705 Ok((kem_output.to_bytes().to_vec(), export))
706 }
707}
708
709impl OpenMlsRand for RustCrypto {
710 type Error = MlsProviderError;
711
712 type RandImpl = rand_chacha::ChaCha20Rng;
713 type BorrowTarget<'a> = RwLockWriteGuard<'a, Self::RandImpl>;
714
715 fn borrow_rand(&self) -> Result<Self::BorrowTarget<'_>, Self::Error> {
716 self.rng.write().map_err(|_| MlsProviderError::RngLockPoison)
717 }
718
719 fn random_array<const N: usize>(&self) -> Result<[u8; N], Self::Error> {
720 let mut rng = self.borrow_rand()?;
721 let mut out = [0u8; N];
722 rng.try_fill_bytes(&mut out)
723 .map_err(|_| MlsProviderError::UnsufficientEntropy)?;
724 Ok(out)
725 }
726
727 fn random_vec(&self, len: usize) -> Result<Vec<u8>, Self::Error> {
728 let mut rng = self.borrow_rand()?;
729 let mut out = vec![0u8; len];
730 rng.try_fill_bytes(&mut out)
731 .map_err(|_| MlsProviderError::UnsufficientEntropy)?;
732 Ok(out)
733 }
734}