1use std::sync::{Arc, 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 crate::{EntropySeed, MlsProviderError};
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> {
239 let mut rng = self.rng.write().map_err(|_| CryptoError::InsufficientRandomness)?;
240
241 match alg {
242 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
243 let sk = p256::ecdsa::SigningKey::random(&mut *rng);
244 let pk = sk.verifying_key().to_sec1_bytes().to_vec();
245 Ok((sk.to_bytes().to_vec(), pk))
246 }
247 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
248 let sk = p384::ecdsa::SigningKey::random(&mut *rng);
249 let pk = sk.verifying_key().to_sec1_bytes().to_vec();
250 Ok((sk.to_bytes().to_vec(), pk))
251 }
252 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
253 let sk = p521::ecdsa::SigningKey::random(&mut *rng);
254 let pk = p521::ecdsa::VerifyingKey::from(&sk)
255 .to_encoded_point(false)
256 .to_bytes()
257 .into();
258 Ok((sk.to_bytes().to_vec(), pk))
259 }
260 SignatureScheme::ED25519 => {
261 let k = ed25519_dalek::SigningKey::generate(&mut *rng);
262 let pk = k.verifying_key();
263 Ok((k.to_bytes().into(), pk.to_bytes().into()))
264 }
265 _ => Err(CryptoError::UnsupportedSignatureScheme),
266 }
267 }
268
269 fn validate_signature_key(&self, alg: SignatureScheme, key: &[u8]) -> Result<(), CryptoError> {
270 match alg {
271 SignatureScheme::ED25519 => {
272 ed25519_dalek::VerifyingKey::try_from(key).map_err(|_| CryptoError::InvalidKey)?;
273 }
274 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
275 p256::ecdsa::VerifyingKey::try_from(key).map_err(|_| CryptoError::InvalidKey)?;
276 }
277 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
278 p384::ecdsa::VerifyingKey::try_from(key).map_err(|_| CryptoError::InvalidKey)?;
279 }
280 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
281 p521::ecdsa::VerifyingKey::from_sec1_bytes(key).map_err(|_| CryptoError::InvalidKey)?;
282 }
283 SignatureScheme::ED448 => {
284 return Err(CryptoError::UnsupportedSignatureScheme);
285 }
286 }
287 Ok(())
288 }
289
290 fn verify_signature(
291 &self,
292 alg: SignatureScheme,
293 data: &[u8],
294 pk: &[u8],
295 signature: &[u8],
296 ) -> Result<(), CryptoError> {
297 use signature::Verifier as _;
298 match alg {
299 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
300 let k = p256::ecdsa::VerifyingKey::from_sec1_bytes(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
301
302 let signature =
303 p256::ecdsa::DerSignature::from_bytes(signature).map_err(|_| CryptoError::InvalidSignature)?;
304
305 k.verify(data, &signature).map_err(|_| CryptoError::InvalidSignature)
306 }
307 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
308 let k = p384::ecdsa::VerifyingKey::from_sec1_bytes(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
309
310 let signature =
311 p384::ecdsa::DerSignature::from_bytes(signature).map_err(|_| CryptoError::InvalidSignature)?;
312
313 k.verify(data, &signature).map_err(|_| CryptoError::InvalidSignature)
314 }
315 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
316 let k = p521::ecdsa::VerifyingKey::from_sec1_bytes(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
317
318 let signature =
319 p521::ecdsa::Signature::from_der(signature).map_err(|_| CryptoError::InvalidSignature)?;
320
321 k.verify(data, &signature).map_err(|_| CryptoError::InvalidSignature)
322 }
323 SignatureScheme::ED25519 => {
324 let k = ed25519_dalek::VerifyingKey::try_from(pk).map_err(|_| CryptoError::CryptoLibraryError)?;
325
326 let sig = ed25519_dalek::Signature::from_slice(signature).map_err(|_| CryptoError::InvalidSignature)?;
327
328 k.verify_strict(data, &sig).map_err(|_| CryptoError::InvalidSignature)
329 }
330 _ => Err(CryptoError::UnsupportedSignatureScheme),
331 }
332 }
333
334 fn sign(&self, alg: SignatureScheme, data: &[u8], key: &[u8]) -> Result<Vec<u8>, CryptoError> {
335 use signature::Signer as _;
336
337 match alg {
338 SignatureScheme::ECDSA_SECP256R1_SHA256 => {
339 let k = p256::ecdsa::SigningKey::from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
340 let signature: p256::ecdsa::DerSignature =
341 k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?;
342 Ok(signature.to_bytes().into())
343 }
344 SignatureScheme::ECDSA_SECP384R1_SHA384 => {
345 let k = p384::ecdsa::SigningKey::from_slice(key).map_err(|_| CryptoError::CryptoLibraryError)?;
346 let signature: p384::ecdsa::DerSignature =
347 k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?;
348 Ok(signature.to_bytes().into())
349 }
350 SignatureScheme::ECDSA_SECP521R1_SHA512 => {
351 let k = p521::ecdsa::SigningKey::from_slice(&*normalize_p521_secret_key(key))
352 .map_err(|_| CryptoError::CryptoLibraryError)?;
353 let signature: p521::ecdsa::DerSignature =
354 k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?.to_der();
355 Ok(signature.to_bytes().into())
356 }
357 SignatureScheme::ED25519 => {
358 let k = Self::normalize_ed25519_key(key)?;
359 let signature = k.try_sign(data).map_err(|_| CryptoError::CryptoLibraryError)?;
360 Ok(signature.to_bytes().into())
361 }
362 _ => Err(CryptoError::UnsupportedSignatureScheme),
363 }
364 }
365
366 fn hpke_seal(
367 &self,
368 config: HpkeConfig,
369 pk_r: &[u8],
370 info: &[u8],
371 aad: &[u8],
372 ptxt: &[u8],
373 ) -> Result<types::HpkeCiphertext, CryptoError> {
374 let mut rng = self.rng.write().map_err(|_| CryptoError::InsufficientRandomness)?;
375
376 match config {
377 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
378 hpke_core::hpke_seal::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
379 pk_r, info, aad, ptxt, &mut *rng,
380 )
381 }
382 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
383 hpke_core::hpke_seal::<hpke::aead::ChaCha20Poly1305, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
384 pk_r, info, aad, ptxt, &mut *rng,
385 )
386 }
387 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
388 hpke_core::hpke_seal::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::DhP256HkdfSha256>(
389 pk_r, info, aad, ptxt, &mut *rng,
390 )
391 }
392 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
393 hpke_core::hpke_seal::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha384, hpke::kem::DhP384HkdfSha384>(
394 pk_r, info, aad, ptxt, &mut *rng,
395 )
396 }
397 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
398 hpke_core::hpke_seal::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha512, hpke::kem::DhP521HkdfSha512>(
399 pk_r, info, aad, ptxt, &mut *rng,
400 )
401 }
402 _ => Err(CryptoError::UnsupportedKem),
403 }
404 }
405
406 fn hpke_open(
407 &self,
408 config: HpkeConfig,
409 input: &types::HpkeCiphertext,
410 sk_r: &[u8],
411 info: &[u8],
412 aad: &[u8],
413 ) -> Result<Vec<u8>, CryptoError> {
414 let plaintext = match config {
415 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
416 hpke_core::hpke_open::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
417 sk_r,
418 input.kem_output.as_slice(),
419 info,
420 aad,
421 input.ciphertext.as_slice(),
422 )?
423 }
424 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
425 hpke_core::hpke_open::<hpke::aead::ChaCha20Poly1305, hpke::kdf::HkdfSha256, hpke::kem::X25519HkdfSha256>(
426 sk_r,
427 input.kem_output.as_slice(),
428 info,
429 aad,
430 input.ciphertext.as_slice(),
431 )?
432 }
433 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
434 hpke_core::hpke_open::<hpke::aead::AesGcm128, hpke::kdf::HkdfSha256, hpke::kem::DhP256HkdfSha256>(
435 sk_r,
436 input.kem_output.as_slice(),
437 info,
438 aad,
439 input.ciphertext.as_slice(),
440 )?
441 }
442 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
443 hpke_core::hpke_open::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha384, hpke::kem::DhP384HkdfSha384>(
444 sk_r,
445 input.kem_output.as_slice(),
446 info,
447 aad,
448 input.ciphertext.as_slice(),
449 )?
450 }
451 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
452 hpke_core::hpke_open::<hpke::aead::AesGcm256, hpke::kdf::HkdfSha512, hpke::kem::DhP521HkdfSha512>(
453 sk_r,
454 input.kem_output.as_slice(),
455 info,
456 aad,
457 input.ciphertext.as_slice(),
458 )?
459 }
460 _ => return Err(CryptoError::UnsupportedKem),
461 };
462
463 Ok(plaintext)
464 }
465
466 fn hpke_setup_sender_and_export(
467 &self,
468 config: HpkeConfig,
469 pk_r: &[u8],
470 info: &[u8],
471 exporter_context: &[u8],
472 exporter_length: usize,
473 ) -> Result<(Vec<u8>, ExporterSecret), CryptoError> {
474 let mut rng = self.rng.write().map_err(|_| CryptoError::InsufficientRandomness)?;
475
476 let (kem_output, export) =
477 match config {
478 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
479 hpke_core::hpke_export_tx::<
480 hpke::aead::AesGcm128,
481 hpke::kdf::HkdfSha256,
482 hpke::kem::X25519HkdfSha256,
483 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
484 }
485 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
486 hpke_core::hpke_export_tx::<
487 hpke::aead::ChaCha20Poly1305,
488 hpke::kdf::HkdfSha256,
489 hpke::kem::X25519HkdfSha256,
490 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
491 }
492 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
493 hpke_core::hpke_export_tx::<
494 hpke::aead::AesGcm128,
495 hpke::kdf::HkdfSha256,
496 hpke::kem::DhP256HkdfSha256,
497 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
498 }
499 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
500 hpke_core::hpke_export_tx::<
501 hpke::aead::AesGcm256,
502 hpke::kdf::HkdfSha384,
503 hpke::kem::DhP384HkdfSha384,
504 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
505 }
506 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
507 hpke_core::hpke_export_tx::<
508 hpke::aead::AesGcm256,
509 hpke::kdf::HkdfSha512,
510 hpke::kem::DhP521HkdfSha512,
511 >(pk_r, info, exporter_context, exporter_length, &mut *rng)?
512 }
513 _ => return Err(CryptoError::UnsupportedKem),
514 };
515
516 debug_assert_eq!(export.len(), exporter_length);
517
518 Ok((kem_output, export.into()))
519 }
520
521 fn hpke_setup_receiver_and_export(
522 &self,
523 config: HpkeConfig,
524 enc: &[u8],
525 sk_r: &[u8],
526 info: &[u8],
527 exporter_context: &[u8],
528 exporter_length: usize,
529 ) -> Result<ExporterSecret, CryptoError> {
530 let export =
531 match config {
532 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
533 hpke_core::hpke_export_rx::<
534 hpke::aead::AesGcm128,
535 hpke::kdf::HkdfSha256,
536 hpke::kem::X25519HkdfSha256,
537 >(enc, sk_r, info, exporter_context, exporter_length)?
538 }
539 HpkeConfig(HpkeKemType::DhKem25519, HpkeKdfType::HkdfSha256, HpkeAeadType::ChaCha20Poly1305) => {
540 hpke_core::hpke_export_rx::<
541 hpke::aead::ChaCha20Poly1305,
542 hpke::kdf::HkdfSha256,
543 hpke::kem::X25519HkdfSha256,
544 >(enc, sk_r, info, exporter_context, exporter_length)?
545 }
546 HpkeConfig(HpkeKemType::DhKemP256, HpkeKdfType::HkdfSha256, HpkeAeadType::AesGcm128) => {
547 hpke_core::hpke_export_rx::<
548 hpke::aead::AesGcm128,
549 hpke::kdf::HkdfSha256,
550 hpke::kem::DhP256HkdfSha256,
551 >(enc, sk_r, info, exporter_context, exporter_length)?
552 }
553 HpkeConfig(HpkeKemType::DhKemP384, HpkeKdfType::HkdfSha384, HpkeAeadType::AesGcm256) => {
554 hpke_core::hpke_export_rx::<
555 hpke::aead::AesGcm256,
556 hpke::kdf::HkdfSha384,
557 hpke::kem::DhP384HkdfSha384,
558 >(enc, sk_r, info, exporter_context, exporter_length)?
559 }
560 HpkeConfig(HpkeKemType::DhKemP521, HpkeKdfType::HkdfSha512, HpkeAeadType::AesGcm256) => {
561 hpke_core::hpke_export_rx::<
562 hpke::aead::AesGcm256,
563 hpke::kdf::HkdfSha512,
564 hpke::kem::DhP521HkdfSha512,
565 >(enc, sk_r, info, exporter_context, exporter_length)?
566 }
567 _ => return Err(CryptoError::UnsupportedKem),
568 };
569
570 debug_assert_eq!(export.len(), exporter_length);
571
572 Ok(export.into())
573 }
574
575 fn derive_hpke_keypair(&self, config: HpkeConfig, ikm: &[u8]) -> Result<types::HpkeKeyPair, CryptoError> {
576 match config.0 {
577 HpkeKemType::DhKemP256 => hpke_core::hpke_derive_keypair::<hpke::kem::DhP256HkdfSha256>(ikm),
578 HpkeKemType::DhKemP384 => hpke_core::hpke_derive_keypair::<hpke::kem::DhP384HkdfSha384>(ikm),
579 HpkeKemType::DhKemP521 => hpke_core::hpke_derive_keypair::<hpke::kem::DhP521HkdfSha512>(ikm),
580 HpkeKemType::DhKem25519 => hpke_core::hpke_derive_keypair::<hpke::kem::X25519HkdfSha256>(ikm),
581 _ => Err(CryptoError::UnsupportedKem),
582 }
583 }
584}
585
586mod hpke_core {
587 use openmls_traits::types::{CryptoError, HpkeCiphertext, HpkeKeyPair};
588
589 pub(crate) fn hpke_open<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
590 private_key: &[u8],
591 kem_output: &[u8],
592 info: &[u8],
593 aad: &[u8],
594 ciphertext: &[u8],
595 ) -> Result<Vec<u8>, CryptoError> {
596 use hpke::{Deserializable as _, Serializable as _};
597 let encapped_key = Kem::EncappedKey::from_bytes(kem_output).map_err(|_| CryptoError::HpkeDecryptionError)?;
598 let sk_len = Kem::PrivateKey::size();
600 let mut sk_buf = zeroize::Zeroizing::new(Vec::with_capacity(sk_len));
601 if private_key.len() < sk_len {
602 for _ in 0..(sk_len - private_key.len()) {
603 sk_buf.push(0x00);
604 }
605 }
606 sk_buf.extend_from_slice(private_key);
607 let key = Kem::PrivateKey::from_bytes(&sk_buf).map_err(|_| CryptoError::HpkeDecryptionError)?;
608 let plaintext =
609 hpke::single_shot_open::<Aead, Kdf, Kem>(&hpke::OpModeR::Base, &key, &encapped_key, info, ciphertext, aad)
610 .map_err(|_| CryptoError::HpkeDecryptionError)?;
611
612 Ok(plaintext)
613 }
614
615 pub(crate) fn hpke_seal<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
616 public_key: &[u8],
617 info: &[u8],
618 aad: &[u8],
619 plaintext: &[u8],
620 csprng: &mut impl rand_core::CryptoRngCore,
621 ) -> Result<HpkeCiphertext, CryptoError> {
622 use hpke::{Deserializable as _, Serializable as _};
623 let key = Kem::PublicKey::from_bytes(public_key).map_err(|_| CryptoError::HpkeEncryptionError)?;
624 let (encapped, ciphertext) =
625 hpke::single_shot_seal::<Aead, Kdf, Kem, _>(&hpke::OpModeS::Base, &key, info, plaintext, aad, csprng)
626 .map_err(|_| CryptoError::HpkeEncryptionError)?;
627
628 Ok(HpkeCiphertext {
629 kem_output: encapped.to_bytes().to_vec().into(),
630 ciphertext: ciphertext.into(),
631 })
632 }
633
634 #[allow(dead_code)]
635 pub(crate) fn hpke_gen_keypair<Kem: hpke::Kem>(
636 csprng: &mut impl rand_core::CryptoRngCore,
637 ) -> Result<HpkeKeyPair, CryptoError> {
638 use hpke::Serializable as _;
639 let (sk, pk) = Kem::gen_keypair(csprng);
640 let (private, public) = (sk.to_bytes().to_vec().into(), pk.to_bytes().to_vec());
641
642 Ok(HpkeKeyPair { private, public })
643 }
644
645 pub(crate) fn hpke_derive_keypair<Kem: hpke::Kem>(ikm: &[u8]) -> Result<HpkeKeyPair, CryptoError> {
646 use hpke::Serializable as _;
647 let (sk, pk) = Kem::derive_keypair(ikm);
648 let (private, public) = (sk.to_bytes().to_vec().into(), pk.to_bytes().to_vec());
649
650 Ok(HpkeKeyPair { private, public })
651 }
652
653 pub(crate) fn hpke_export_rx<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
654 encapped_key: &[u8],
655 rx_private_key: &[u8],
656 info: &[u8],
657 export_info: &[u8],
658 export_len: usize,
659 ) -> Result<Vec<u8>, CryptoError> {
660 use hpke::Deserializable as _;
661 let key = Kem::PrivateKey::from_bytes(rx_private_key).map_err(|_| CryptoError::ReceiverSetupError)?;
662 let encapped_key = Kem::EncappedKey::from_bytes(encapped_key).map_err(|_| CryptoError::ReceiverSetupError)?;
663 let ctx = hpke::setup_receiver::<Aead, Kdf, Kem>(&hpke::OpModeR::Base, &key, &encapped_key, info)
664 .map_err(|_| CryptoError::ReceiverSetupError)?;
665
666 let mut export = vec![0u8; export_len];
667
668 ctx.export(export_info, &mut export)
669 .map_err(|_| CryptoError::ExporterError)?;
670
671 Ok(export)
672 }
673
674 pub(crate) fn hpke_export_tx<Aead: hpke::aead::Aead, Kdf: hpke::kdf::Kdf, Kem: hpke::Kem>(
675 tx_public_key: &[u8],
676 info: &[u8],
677 export_info: &[u8],
678 export_len: usize,
679 csprng: &mut impl rand_core::CryptoRngCore,
680 ) -> Result<(Vec<u8>, Vec<u8>), CryptoError> {
681 use hpke::{Deserializable as _, Serializable as _};
682 let key = Kem::PublicKey::from_bytes(tx_public_key).map_err(|_| CryptoError::SenderSetupError)?;
683 let (kem_output, ctx) = hpke::setup_sender::<Aead, Kdf, Kem, _>(&hpke::OpModeS::Base, &key, info, csprng)
684 .map_err(|_| CryptoError::SenderSetupError)?;
685
686 let mut export = vec![0u8; export_len];
687
688 ctx.export(export_info, &mut export)
689 .map_err(|_| CryptoError::ExporterError)?;
690
691 Ok((kem_output.to_bytes().to_vec(), export))
692 }
693}
694
695impl OpenMlsRand for RustCrypto {
696 type Error = MlsProviderError;
697
698 type RandImpl = rand_chacha::ChaCha20Rng;
699 type BorrowTarget<'a> = RwLockWriteGuard<'a, Self::RandImpl>;
700
701 fn borrow_rand(&self) -> Result<Self::BorrowTarget<'_>, Self::Error> {
702 self.rng.write().map_err(|_| MlsProviderError::RngLockPoison)
703 }
704
705 fn random_array<const N: usize>(&self) -> Result<[u8; N], Self::Error> {
706 let mut rng = self.borrow_rand()?;
707 let mut out = [0u8; N];
708 rng.try_fill_bytes(&mut out)
709 .map_err(|_| MlsProviderError::UnsufficientEntropy)?;
710 Ok(out)
711 }
712
713 fn random_vec(&self, len: usize) -> Result<Vec<u8>, Self::Error> {
714 let mut rng = self.borrow_rand()?;
715 let mut out = vec![0u8; len];
716 rng.try_fill_bytes(&mut out)
717 .map_err(|_| MlsProviderError::UnsufficientEntropy)?;
718 Ok(out)
719 }
720}