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