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