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