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