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