xref: /aosp_15_r20/system/security/mls/mls-rs-crypto-boringssl/src/lib.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Implements mls_rs_core's CryptoProvider and CipherSuiteProvider backed by BoringSSL.
16 
17 pub mod aead;
18 pub mod ecdh;
19 pub mod eddsa;
20 pub mod hash;
21 pub mod hpke;
22 pub mod kdf;
23 
24 #[cfg(test)]
25 mod test_helpers;
26 
27 use mls_rs_core::crypto::{
28     CipherSuite, CipherSuiteProvider, CryptoProvider, HpkeCiphertext, HpkePublicKey, HpkeSecretKey,
29     SignaturePublicKey, SignatureSecretKey,
30 };
31 use mls_rs_core::error::{AnyError, IntoAnyError};
32 use mls_rs_crypto_traits::{AeadType, KdfType, KemType};
33 use thiserror::Error;
34 use zeroize::Zeroizing;
35 
36 use aead::AeadWrapper;
37 use ecdh::Ecdh;
38 use eddsa::{EdDsa, EdDsaError};
39 use hash::{Hash, HashError};
40 use hpke::{ContextR, ContextS, DhKem, Hpke, HpkeError};
41 use kdf::Kdf;
42 
43 /// Errors returned from BoringsslCryptoProvider.
44 #[derive(Debug, Error)]
45 pub enum BoringsslCryptoError {
46     /// Error returned from hash functions and HMACs.
47     #[error(transparent)]
48     HashError(#[from] HashError),
49     /// Error returned from KEMs.
50     #[error(transparent)]
51     KemError(AnyError),
52     /// Error returned from KDFs.
53     #[error(transparent)]
54     KdfError(AnyError),
55     /// Error returned from AEADs.
56     #[error(transparent)]
57     AeadError(AnyError),
58     /// Error returned from HPKE.
59     #[error(transparent)]
60     HpkeError(#[from] HpkeError),
61     /// Error returned from EdDSA.
62     #[error(transparent)]
63     EdDsaError(#[from] EdDsaError),
64 }
65 
66 impl IntoAnyError for BoringsslCryptoError {
into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self>67     fn into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self> {
68         Ok(self.into())
69     }
70 }
71 
72 /// CryptoProvider trait implementation backed by BoringSSL.
73 #[derive(Debug, Clone)]
74 #[non_exhaustive]
75 pub struct BoringsslCryptoProvider {
76     /// Available cipher suites.
77     pub enabled_cipher_suites: Vec<CipherSuite>,
78 }
79 
80 impl BoringsslCryptoProvider {
81     /// Creates a new BoringsslCryptoProvider.
new() -> Self82     pub fn new() -> Self {
83         Default::default()
84     }
85 
86     /// Sets the enabled cipher suites.
with_enabled_cipher_suites(enabled_cipher_suites: Vec<CipherSuite>) -> Self87     pub fn with_enabled_cipher_suites(enabled_cipher_suites: Vec<CipherSuite>) -> Self {
88         Self { enabled_cipher_suites }
89     }
90 
91     /// Returns all available cipher suites.
all_supported_cipher_suites() -> Vec<CipherSuite>92     pub fn all_supported_cipher_suites() -> Vec<CipherSuite> {
93         vec![CipherSuite::CURVE25519_AES128, CipherSuite::CURVE25519_CHACHA]
94     }
95 }
96 
97 impl Default for BoringsslCryptoProvider {
default() -> Self98     fn default() -> Self {
99         Self { enabled_cipher_suites: Self::all_supported_cipher_suites() }
100     }
101 }
102 
103 impl CryptoProvider for BoringsslCryptoProvider {
104     type CipherSuiteProvider = BoringsslCipherSuite<DhKem<Ecdh, Kdf>, Kdf, AeadWrapper>;
105 
supported_cipher_suites(&self) -> Vec<CipherSuite>106     fn supported_cipher_suites(&self) -> Vec<CipherSuite> {
107         self.enabled_cipher_suites.clone()
108     }
109 
cipher_suite_provider( &self, cipher_suite: CipherSuite, ) -> Option<Self::CipherSuiteProvider>110     fn cipher_suite_provider(
111         &self,
112         cipher_suite: CipherSuite,
113     ) -> Option<Self::CipherSuiteProvider> {
114         if !self.enabled_cipher_suites.contains(&cipher_suite) {
115             return None;
116         }
117 
118         let ecdh = Ecdh::new(cipher_suite)?;
119         let kdf = Kdf::new(cipher_suite)?;
120         let kem = DhKem::new(cipher_suite, ecdh, kdf.clone())?;
121         let aead = AeadWrapper::new(cipher_suite)?;
122 
123         BoringsslCipherSuite::new(cipher_suite, kem, kdf, aead)
124     }
125 }
126 
127 /// CipherSuiteProvider trait implementation backed by BoringSSL.
128 #[derive(Clone)]
129 pub struct BoringsslCipherSuite<KEM, KDF, AEAD>
130 where
131     KEM: KemType + Clone,
132     KDF: KdfType + Clone,
133     AEAD: AeadType + Clone,
134 {
135     cipher_suite: CipherSuite,
136     hash: Hash,
137     kem: KEM,
138     kdf: KDF,
139     aead: AEAD,
140     hpke: Hpke,
141     eddsa: EdDsa,
142 }
143 
144 impl<KEM, KDF, AEAD> BoringsslCipherSuite<KEM, KDF, AEAD>
145 where
146     KEM: KemType + Clone,
147     KDF: KdfType + Clone,
148     AEAD: AeadType + Clone,
149 {
150     /// Creates a new BoringsslCipherSuite.
new(cipher_suite: CipherSuite, kem: KEM, kdf: KDF, aead: AEAD) -> Option<Self>151     pub fn new(cipher_suite: CipherSuite, kem: KEM, kdf: KDF, aead: AEAD) -> Option<Self> {
152         Some(Self {
153             cipher_suite,
154             hash: Hash::new(cipher_suite).ok()?,
155             kem,
156             kdf,
157             aead,
158             hpke: Hpke::new(cipher_suite),
159             eddsa: EdDsa::new(cipher_suite)?,
160         })
161     }
162 
163     /// Returns random bytes generated via BoringSSL.
random_bytes(&self, out: &mut [u8]) -> Result<(), BoringsslCryptoError>164     pub fn random_bytes(&self, out: &mut [u8]) -> Result<(), BoringsslCryptoError> {
165         bssl_crypto::rand_bytes(out);
166         Ok(())
167     }
168 }
169 
170 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
171 #[cfg_attr(all(target_arch = "wasm32", mls_build_async), maybe_async::must_be_async(?Send))]
172 #[cfg_attr(all(not(target_arch = "wasm32"), mls_build_async), maybe_async::must_be_async)]
173 impl<KEM, KDF, AEAD> CipherSuiteProvider for BoringsslCipherSuite<KEM, KDF, AEAD>
174 where
175     KEM: KemType + Clone + Send + Sync,
176     KDF: KdfType + Clone + Send + Sync,
177     AEAD: AeadType + Clone + Send + Sync,
178 {
179     type Error = BoringsslCryptoError;
180     type HpkeContextS = ContextS;
181     type HpkeContextR = ContextR;
182 
cipher_suite(&self) -> CipherSuite183     fn cipher_suite(&self) -> CipherSuite {
184         self.cipher_suite
185     }
186 
random_bytes(&self, out: &mut [u8]) -> Result<(), Self::Error>187     fn random_bytes(&self, out: &mut [u8]) -> Result<(), Self::Error> {
188         self.random_bytes(out)
189     }
190 
hash(&self, data: &[u8]) -> Result<Vec<u8>, Self::Error>191     async fn hash(&self, data: &[u8]) -> Result<Vec<u8>, Self::Error> {
192         Ok(self.hash.hash(data))
193     }
194 
mac(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>, Self::Error>195     async fn mac(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>, Self::Error> {
196         Ok(self.hash.mac(key, data)?)
197     }
198 
kem_generate(&self) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error>199     async fn kem_generate(&self) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error> {
200         self.kem.generate().await.map_err(|e| BoringsslCryptoError::KemError(e.into_any_error()))
201     }
202 
kem_derive(&self, ikm: &[u8]) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error>203     async fn kem_derive(&self, ikm: &[u8]) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error> {
204         self.kem.derive(ikm).await.map_err(|e| BoringsslCryptoError::KemError(e.into_any_error()))
205     }
206 
kem_public_key_validate(&self, key: &HpkePublicKey) -> Result<(), Self::Error>207     fn kem_public_key_validate(&self, key: &HpkePublicKey) -> Result<(), Self::Error> {
208         self.kem
209             .public_key_validate(key)
210             .map_err(|e| BoringsslCryptoError::KemError(e.into_any_error()))
211     }
212 
kdf_extract( &self, salt: &[u8], ikm: &[u8], ) -> Result<Zeroizing<Vec<u8>>, Self::Error>213     async fn kdf_extract(
214         &self,
215         salt: &[u8],
216         ikm: &[u8],
217     ) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
218         self.kdf
219             .extract(salt, ikm)
220             .await
221             .map_err(|e| BoringsslCryptoError::KdfError(e.into_any_error()))
222             .map(Zeroizing::new)
223     }
224 
kdf_expand( &self, prk: &[u8], info: &[u8], len: usize, ) -> Result<Zeroizing<Vec<u8>>, Self::Error>225     async fn kdf_expand(
226         &self,
227         prk: &[u8],
228         info: &[u8],
229         len: usize,
230     ) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
231         self.kdf
232             .expand(prk, info, len)
233             .await
234             .map_err(|e| BoringsslCryptoError::KdfError(e.into_any_error()))
235             .map(Zeroizing::new)
236     }
237 
kdf_extract_size(&self) -> usize238     fn kdf_extract_size(&self) -> usize {
239         self.kdf.extract_size()
240     }
241 
aead_seal( &self, key: &[u8], data: &[u8], aad: Option<&[u8]>, nonce: &[u8], ) -> Result<Vec<u8>, Self::Error>242     async fn aead_seal(
243         &self,
244         key: &[u8],
245         data: &[u8],
246         aad: Option<&[u8]>,
247         nonce: &[u8],
248     ) -> Result<Vec<u8>, Self::Error> {
249         self.aead
250             .seal(key, data, aad, nonce)
251             .await
252             .map_err(|e| BoringsslCryptoError::AeadError(e.into_any_error()))
253     }
254 
aead_open( &self, key: &[u8], cipher_text: &[u8], aad: Option<&[u8]>, nonce: &[u8], ) -> Result<Zeroizing<Vec<u8>>, Self::Error>255     async fn aead_open(
256         &self,
257         key: &[u8],
258         cipher_text: &[u8],
259         aad: Option<&[u8]>,
260         nonce: &[u8],
261     ) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
262         self.aead
263             .open(key, cipher_text, aad, nonce)
264             .await
265             .map_err(|e| BoringsslCryptoError::AeadError(e.into_any_error()))
266             .map(Zeroizing::new)
267     }
268 
aead_key_size(&self) -> usize269     fn aead_key_size(&self) -> usize {
270         self.aead.key_size()
271     }
272 
aead_nonce_size(&self) -> usize273     fn aead_nonce_size(&self) -> usize {
274         self.aead.nonce_size()
275     }
276 
hpke_setup_s( &self, remote_key: &HpkePublicKey, info: &[u8], ) -> Result<(Vec<u8>, Self::HpkeContextS), Self::Error>277     async fn hpke_setup_s(
278         &self,
279         remote_key: &HpkePublicKey,
280         info: &[u8],
281     ) -> Result<(Vec<u8>, Self::HpkeContextS), Self::Error> {
282         Ok(self.hpke.setup_sender(remote_key, info).await?)
283     }
284 
hpke_seal( &self, remote_key: &HpkePublicKey, info: &[u8], aad: Option<&[u8]>, pt: &[u8], ) -> Result<HpkeCiphertext, Self::Error>285     async fn hpke_seal(
286         &self,
287         remote_key: &HpkePublicKey,
288         info: &[u8],
289         aad: Option<&[u8]>,
290         pt: &[u8],
291     ) -> Result<HpkeCiphertext, Self::Error> {
292         Ok(self.hpke.seal(remote_key, info, aad, pt).await?)
293     }
294 
hpke_setup_r( &self, enc: &[u8], local_secret: &HpkeSecretKey, _local_public: &HpkePublicKey, info: &[u8], ) -> Result<Self::HpkeContextR, Self::Error>295     async fn hpke_setup_r(
296         &self,
297         enc: &[u8],
298         local_secret: &HpkeSecretKey,
299         // Other implementations use `_local_public` to skip derivation of the public from the
300         // private key for the KEM decapsulation step, but BoringSSL's API does not accept a public
301         // key and instead derives it under the hood.
302         _local_public: &HpkePublicKey,
303         info: &[u8],
304     ) -> Result<Self::HpkeContextR, Self::Error> {
305         Ok(self.hpke.setup_receiver(enc, local_secret, info).await?)
306     }
307 
hpke_open( &self, ciphertext: &HpkeCiphertext, local_secret: &HpkeSecretKey, _local_public: &HpkePublicKey, info: &[u8], aad: Option<&[u8]>, ) -> Result<Vec<u8>, Self::Error>308     async fn hpke_open(
309         &self,
310         ciphertext: &HpkeCiphertext,
311         local_secret: &HpkeSecretKey,
312         // Other implementations use `_local_public` to skip derivation of the public from the
313         // private key for hpke_setup_r()'s KEM decapsulation step, but BoringSSL's API does not
314         // accept a public key and instead derives it under the hood.
315         _local_public: &HpkePublicKey,
316         info: &[u8],
317         aad: Option<&[u8]>,
318     ) -> Result<Vec<u8>, Self::Error> {
319         Ok(self.hpke.open(ciphertext, local_secret, info, aad).await?)
320     }
321 
signature_key_generate( &self, ) -> Result<(SignatureSecretKey, SignaturePublicKey), Self::Error>322     async fn signature_key_generate(
323         &self,
324     ) -> Result<(SignatureSecretKey, SignaturePublicKey), Self::Error> {
325         Ok(self.eddsa.signature_key_generate()?)
326     }
327 
signature_key_derive_public( &self, secret_key: &SignatureSecretKey, ) -> Result<SignaturePublicKey, Self::Error>328     async fn signature_key_derive_public(
329         &self,
330         secret_key: &SignatureSecretKey,
331     ) -> Result<SignaturePublicKey, Self::Error> {
332         Ok(self.eddsa.signature_key_derive_public(secret_key)?)
333     }
334 
sign( &self, secret_key: &SignatureSecretKey, data: &[u8], ) -> Result<Vec<u8>, Self::Error>335     async fn sign(
336         &self,
337         secret_key: &SignatureSecretKey,
338         data: &[u8],
339     ) -> Result<Vec<u8>, Self::Error> {
340         Ok(self.eddsa.sign(secret_key, data)?)
341     }
342 
verify( &self, public_key: &SignaturePublicKey, signature: &[u8], data: &[u8], ) -> Result<(), Self::Error>343     async fn verify(
344         &self,
345         public_key: &SignaturePublicKey,
346         signature: &[u8],
347         data: &[u8],
348     ) -> Result<(), Self::Error> {
349         Ok(self.eddsa.verify(public_key, signature, data)?)
350     }
351 }
352 
353 #[cfg(all(not(mls_build_async), test))]
354 mod test {
355     use super::BoringsslCryptoProvider;
356     use crate::test_helpers::decode_hex;
357     use mls_rs_core::crypto::{
358         CipherSuite, CipherSuiteProvider, CryptoProvider, HpkeContextR, HpkeContextS,
359         HpkePublicKey, HpkeSecretKey, SignaturePublicKey, SignatureSecretKey,
360     };
361 
get_cipher_suites() -> Vec<CipherSuite>362     fn get_cipher_suites() -> Vec<CipherSuite> {
363         vec![CipherSuite::CURVE25519_AES128, CipherSuite::CURVE25519_CHACHA]
364     }
365 
366     #[test]
supported_cipher_suites()367     fn supported_cipher_suites() {
368         let bssl = BoringsslCryptoProvider::new();
369         assert_eq!(bssl.supported_cipher_suites().len(), 2);
370     }
371 
372     #[test]
unsupported_cipher_suites()373     fn unsupported_cipher_suites() {
374         let bssl = BoringsslCryptoProvider::new();
375         for suite in vec![
376             CipherSuite::P256_AES128,
377             CipherSuite::CURVE448_AES256,
378             CipherSuite::P521_AES256,
379             CipherSuite::CURVE448_CHACHA,
380             CipherSuite::P384_AES256,
381         ] {
382             assert!(bssl.cipher_suite_provider(suite).is_none());
383         }
384     }
385 
386     #[test]
cipher_suite()387     fn cipher_suite() {
388         let bssl = BoringsslCryptoProvider::new();
389         for suite in get_cipher_suites() {
390             let crypto = bssl.cipher_suite_provider(suite).unwrap();
391             assert_eq!(crypto.cipher_suite(), suite);
392         }
393     }
394 
395     #[test]
random_bytes()396     fn random_bytes() {
397         let bssl = BoringsslCryptoProvider::new();
398         for suite in get_cipher_suites() {
399             let crypto = bssl.cipher_suite_provider(suite).unwrap();
400             let mut buf = [0; 32];
401             let _ = crypto.random_bytes(&mut buf);
402         }
403     }
404 
405     #[test]
hash()406     fn hash() {
407         let bssl = BoringsslCryptoProvider::new();
408         for suite in get_cipher_suites() {
409             let crypto = bssl.cipher_suite_provider(suite).unwrap();
410             assert_eq!(
411                 crypto.hash(&decode_hex::<4>("74ba2521")).unwrap(),
412                 // bssl_crypto::hmac test vector.
413                 decode_hex::<32>(
414                     "b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e"
415                 )
416             );
417         }
418     }
419 
420     #[test]
mac()421     fn mac() {
422         let bssl = BoringsslCryptoProvider::new();
423         for suite in get_cipher_suites() {
424             let crypto = bssl.cipher_suite_provider(suite).unwrap();
425             // bssl_crypto::hmac test vector.
426             let expected = vec![
427                 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
428                 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
429                 0x2e, 0x32, 0xcf, 0xf7,
430             ];
431             let key: [u8; 20] = [0x0b; 20];
432             let data = b"Hi There";
433 
434             assert_eq!(crypto.mac(&key, data).unwrap(), expected);
435         }
436     }
437 
438     #[test]
kem_generate()439     fn kem_generate() {
440         let bssl = BoringsslCryptoProvider::new();
441         for suite in get_cipher_suites() {
442             let crypto = bssl.cipher_suite_provider(suite).unwrap();
443             assert!(crypto.kem_generate().is_ok());
444         }
445     }
446 
447     #[test]
kem_derive()448     fn kem_derive() {
449         let bssl = BoringsslCryptoProvider::new();
450         for suite in get_cipher_suites() {
451             let crypto = bssl.cipher_suite_provider(suite).unwrap();
452             // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1.1
453             let ikm: [u8; 32] =
454                 decode_hex("7268600d403fce431561aef583ee1613527cff655c1343f29812e66706df3234");
455             let expected_sk = HpkeSecretKey::from(
456                 decode_hex::<32>(
457                     "52c4a758a802cd8b936eceea314432798d5baf2d7e9235dc084ab1b9cfa2f736",
458                 )
459                 .to_vec(),
460             );
461             let expected_pk = HpkePublicKey::from(
462                 decode_hex::<32>(
463                     "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431",
464                 )
465                 .to_vec(),
466             );
467 
468             let (sk, pk) = crypto.kem_derive(&ikm).unwrap();
469             assert_eq!(sk, expected_sk);
470             assert_eq!(pk, expected_pk);
471         }
472     }
473 
474     #[test]
kem_public_key_validate()475     fn kem_public_key_validate() {
476         let bssl = BoringsslCryptoProvider::new();
477         for suite in get_cipher_suites() {
478             let crypto = bssl.cipher_suite_provider(suite).unwrap();
479             // https://www.rfc-editor.org/rfc/rfc7748.html#section-6.1
480             let public_key = HpkePublicKey::from(
481                 decode_hex::<32>(
482                     "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
483                 )
484                 .to_vec(),
485             );
486             assert!(crypto.kem_public_key_validate(&public_key).is_ok());
487         }
488     }
489 
490     #[test]
kdf_extract_and_expand()491     fn kdf_extract_and_expand() {
492         let bssl = BoringsslCryptoProvider::new();
493         for suite in get_cipher_suites() {
494             let crypto = bssl.cipher_suite_provider(suite).unwrap();
495             // https://www.rfc-editor.org/rfc/rfc5869.html#appendix-A.1
496             let ikm: [u8; 22] = decode_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
497             let salt: [u8; 13] = decode_hex("000102030405060708090a0b0c");
498             let info: [u8; 10] = decode_hex("f0f1f2f3f4f5f6f7f8f9");
499             let expected_prk: [u8; 32] =
500                 decode_hex("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5");
501             let expected_okm : [u8; 42] = decode_hex(
502                     "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
503                 );
504 
505             let prk = crypto.kdf_extract(&salt, &ikm).unwrap();
506             assert_eq!(prk.as_ref(), expected_prk);
507             assert_eq!(crypto.kdf_expand(&prk.as_ref(), &info, 42).unwrap().as_ref(), expected_okm);
508         }
509     }
510 
511     #[test]
kdf_extract_size()512     fn kdf_extract_size() {
513         let bssl = BoringsslCryptoProvider::new();
514         for suite in get_cipher_suites() {
515             let crypto = bssl.cipher_suite_provider(suite).unwrap();
516             assert_eq!(crypto.kdf_extract_size(), 32);
517         }
518     }
519 
520     #[test]
aead()521     fn aead() {
522         let bssl = BoringsslCryptoProvider::new();
523         for suite in get_cipher_suites() {
524             let crypto = bssl.cipher_suite_provider(suite).unwrap();
525             let key = vec![42u8; crypto.aead_key_size()];
526             let associated_data = vec![42u8, 12];
527             let nonce = vec![42u8; crypto.aead_nonce_size()];
528             let plaintext = b"message";
529 
530             let ciphertext =
531                 crypto.aead_seal(&key, plaintext, Some(&associated_data), &nonce).unwrap();
532             assert_eq!(
533                 plaintext,
534                 crypto
535                     .aead_open(&key, ciphertext.as_slice(), Some(&associated_data), &nonce)
536                     .unwrap()
537                     .as_slice()
538             );
539         }
540     }
541 
542     #[test]
hpke_setup_seal_open_export()543     fn hpke_setup_seal_open_export() {
544         let bssl = BoringsslCryptoProvider::new();
545         for suite in get_cipher_suites() {
546             let crypto = bssl.cipher_suite_provider(suite).unwrap();
547             // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1.1
548             let receiver_pub_key = HpkePublicKey::from(
549                 decode_hex::<32>(
550                     "3948cfe0ad1ddb695d780e59077195da6c56506b027329794ab02bca80815c4d",
551                 )
552                 .to_vec(),
553             );
554             let receiver_priv_key = HpkeSecretKey::from(
555                 decode_hex::<32>(
556                     "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8",
557                 )
558                 .to_vec(),
559             );
560 
561             let info = b"some_info";
562             let plaintext = b"plaintext";
563             let associated_data = b"some_ad";
564             let exporter_ctx = b"export_ctx";
565 
566             let (enc, mut sender_ctx) = crypto.hpke_setup_s(&receiver_pub_key, info).unwrap();
567             let mut receiver_ctx =
568                 crypto.hpke_setup_r(&enc, &receiver_priv_key, &receiver_pub_key, info).unwrap();
569             let ct = sender_ctx.seal(Some(associated_data), plaintext).unwrap();
570             assert_eq!(plaintext.as_ref(), receiver_ctx.open(Some(associated_data), &ct).unwrap(),);
571             assert_eq!(
572                 sender_ctx.export(exporter_ctx, 32).unwrap(),
573                 receiver_ctx.export(exporter_ctx, 32).unwrap(),
574             );
575         }
576     }
577 
578     #[test]
hpke_seal_open()579     fn hpke_seal_open() {
580         let bssl = BoringsslCryptoProvider::new();
581         for suite in get_cipher_suites() {
582             let crypto = bssl.cipher_suite_provider(suite).unwrap();
583             // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1.1
584             let receiver_pub_key = HpkePublicKey::from(
585                 decode_hex::<32>(
586                     "3948cfe0ad1ddb695d780e59077195da6c56506b027329794ab02bca80815c4d",
587                 )
588                 .to_vec(),
589             );
590             let receiver_priv_key = HpkeSecretKey::from(
591                 decode_hex::<32>(
592                     "4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8",
593                 )
594                 .to_vec(),
595             );
596 
597             let info = b"some_info";
598             let plaintext = b"plaintext";
599             let associated_data = b"some_ad";
600 
601             let ct = crypto
602                 .hpke_seal(&receiver_pub_key, info, Some(associated_data), plaintext)
603                 .unwrap();
604             assert_eq!(
605                 plaintext.as_ref(),
606                 crypto
607                     .hpke_open(
608                         &ct,
609                         &receiver_priv_key,
610                         &receiver_pub_key,
611                         info,
612                         Some(associated_data)
613                     )
614                     .unwrap(),
615             );
616         }
617     }
618 
619     #[test]
signature_key_generate()620     fn signature_key_generate() {
621         let bssl = BoringsslCryptoProvider::new();
622         for suite in get_cipher_suites() {
623             let crypto = bssl.cipher_suite_provider(suite).unwrap();
624             assert!(crypto.signature_key_generate().is_ok());
625         }
626     }
627 
628     #[test]
signature_key_derive_public()629     fn signature_key_derive_public() {
630         let bssl = BoringsslCryptoProvider::new();
631         for suite in get_cipher_suites() {
632             let crypto = bssl.cipher_suite_provider(suite).unwrap();
633             // Test 1 from https://www.rfc-editor.org/rfc/rfc8032#section-7.1
634             let private_key = SignatureSecretKey::from(
635                 decode_hex::<32>(
636                     "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
637                 )
638                 .to_vec(),
639             );
640             let expected_public_key = SignaturePublicKey::from(
641                 decode_hex::<32>(
642                     "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
643                 )
644                 .to_vec(),
645             );
646 
647             assert_eq!(
648                 crypto.signature_key_derive_public(&private_key).unwrap(),
649                 expected_public_key
650             );
651         }
652     }
653 
654     #[test]
sign_verify()655     fn sign_verify() {
656         let bssl = BoringsslCryptoProvider::new();
657         for suite in get_cipher_suites() {
658             let crypto = bssl.cipher_suite_provider(suite).unwrap();
659             // Test 3 from https://www.rfc-editor.org/rfc/rfc8032#section-7.1
660             let private_key = SignatureSecretKey::from(
661                 decode_hex::<32>(
662                     "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7",
663                 )
664                 .to_vec(),
665             );
666             let data: [u8; 2] = decode_hex("af82");
667             let expected_sig = decode_hex::<64>("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a").to_vec();
668 
669             let sig = crypto.sign(&private_key, &data).unwrap();
670             assert_eq!(sig, expected_sig);
671 
672             let public_key = crypto.signature_key_derive_public(&private_key).unwrap();
673             assert!(crypto.verify(&public_key, &sig, &data).is_ok());
674         }
675     }
676 }
677