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 //! Authenticated encryption with additional data. 16*e1997b9aSAndroid Build Coastguard Worker 17*e1997b9aSAndroid Build Coastguard Worker use bssl_crypto::aead::{Aead, Aes128Gcm, Aes256Gcm, Chacha20Poly1305}; 18*e1997b9aSAndroid Build Coastguard Worker use mls_rs_core::crypto::CipherSuite; 19*e1997b9aSAndroid Build Coastguard Worker use mls_rs_core::error::IntoAnyError; 20*e1997b9aSAndroid Build Coastguard Worker use mls_rs_crypto_traits::{AeadId, AeadType, AES_TAG_LEN}; 21*e1997b9aSAndroid Build Coastguard Worker 22*e1997b9aSAndroid Build Coastguard Worker use core::array::TryFromSliceError; 23*e1997b9aSAndroid Build Coastguard Worker use thiserror::Error; 24*e1997b9aSAndroid Build Coastguard Worker 25*e1997b9aSAndroid Build Coastguard Worker /// Errors returned from AEAD. 26*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Error)] 27*e1997b9aSAndroid Build Coastguard Worker pub enum AeadError { 28*e1997b9aSAndroid Build Coastguard Worker /// Error returned when conversion from slice to array fails. 29*e1997b9aSAndroid Build Coastguard Worker #[error(transparent)] 30*e1997b9aSAndroid Build Coastguard Worker TryFromSliceError(#[from] TryFromSliceError), 31*e1997b9aSAndroid Build Coastguard Worker /// Error returned when the ciphertext is invalid. 32*e1997b9aSAndroid Build Coastguard Worker #[error("AEAD ciphertext was invalid")] 33*e1997b9aSAndroid Build Coastguard Worker InvalidCiphertext, 34*e1997b9aSAndroid Build Coastguard Worker /// Error returned when the ciphertext length is too short. 35*e1997b9aSAndroid Build Coastguard Worker #[error("AEAD ciphertext of length {len}, expected length at least {min_len}")] 36*e1997b9aSAndroid Build Coastguard Worker TooShortCiphertext { 37*e1997b9aSAndroid Build Coastguard Worker /// Invalid ciphertext length. 38*e1997b9aSAndroid Build Coastguard Worker len: usize, 39*e1997b9aSAndroid Build Coastguard Worker /// Minimum ciphertext length. 40*e1997b9aSAndroid Build Coastguard Worker min_len: usize, 41*e1997b9aSAndroid Build Coastguard Worker }, 42*e1997b9aSAndroid Build Coastguard Worker /// Error returned when the plaintext is empty. 43*e1997b9aSAndroid Build Coastguard Worker #[error("message cannot be empty")] 44*e1997b9aSAndroid Build Coastguard Worker EmptyPlaintext, 45*e1997b9aSAndroid Build Coastguard Worker /// Error returned when the key length is invalid. 46*e1997b9aSAndroid Build Coastguard Worker #[error("AEAD key of invalid length {len}, expected length {expected_len}")] 47*e1997b9aSAndroid Build Coastguard Worker InvalidKeyLen { 48*e1997b9aSAndroid Build Coastguard Worker /// Invalid key length. 49*e1997b9aSAndroid Build Coastguard Worker len: usize, 50*e1997b9aSAndroid Build Coastguard Worker /// Expected key length. 51*e1997b9aSAndroid Build Coastguard Worker expected_len: usize, 52*e1997b9aSAndroid Build Coastguard Worker }, 53*e1997b9aSAndroid Build Coastguard Worker /// Error returned when the nonce size is invalid. 54*e1997b9aSAndroid Build Coastguard Worker #[error("AEAD nonce of invalid length {len}, expected length {expected_len}")] 55*e1997b9aSAndroid Build Coastguard Worker InvalidNonceLen { 56*e1997b9aSAndroid Build Coastguard Worker /// Invalid nonce length. 57*e1997b9aSAndroid Build Coastguard Worker len: usize, 58*e1997b9aSAndroid Build Coastguard Worker /// Expected nonce length. 59*e1997b9aSAndroid Build Coastguard Worker expected_len: usize, 60*e1997b9aSAndroid Build Coastguard Worker }, 61*e1997b9aSAndroid Build Coastguard Worker /// Error returned when unsupported cipher suite is requested. 62*e1997b9aSAndroid Build Coastguard Worker #[error("unsupported cipher suite")] 63*e1997b9aSAndroid Build Coastguard Worker UnsupportedCipherSuite, 64*e1997b9aSAndroid Build Coastguard Worker } 65*e1997b9aSAndroid Build Coastguard Worker 66*e1997b9aSAndroid Build Coastguard Worker impl IntoAnyError for AeadError { 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 /// AeadType implementation backed by BoringSSL. 73*e1997b9aSAndroid Build Coastguard Worker #[derive(Clone)] 74*e1997b9aSAndroid Build Coastguard Worker pub struct AeadWrapper(AeadId); 75*e1997b9aSAndroid Build Coastguard Worker 76*e1997b9aSAndroid Build Coastguard Worker impl AeadWrapper { 77*e1997b9aSAndroid Build Coastguard Worker /// Creates a new AeadWrapper. new(cipher_suite: CipherSuite) -> Option<Self>78*e1997b9aSAndroid Build Coastguard Worker pub fn new(cipher_suite: CipherSuite) -> Option<Self> { 79*e1997b9aSAndroid Build Coastguard Worker AeadId::new(cipher_suite).map(Self) 80*e1997b9aSAndroid Build Coastguard Worker } 81*e1997b9aSAndroid Build Coastguard Worker } 82*e1997b9aSAndroid Build Coastguard Worker 83*e1997b9aSAndroid Build Coastguard Worker #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] 84*e1997b9aSAndroid Build Coastguard Worker #[cfg_attr(all(target_arch = "wasm32", mls_build_async), maybe_async::must_be_async(?Send))] 85*e1997b9aSAndroid Build Coastguard Worker #[cfg_attr(all(not(target_arch = "wasm32"), mls_build_async), maybe_async::must_be_async)] 86*e1997b9aSAndroid Build Coastguard Worker impl AeadType for AeadWrapper { 87*e1997b9aSAndroid Build Coastguard Worker type Error = AeadError; 88*e1997b9aSAndroid Build Coastguard Worker seal<'a>( &self, key: &[u8], data: &[u8], aad: Option<&'a [u8]>, nonce: &[u8], ) -> Result<Vec<u8>, AeadError>89*e1997b9aSAndroid Build Coastguard Worker async fn seal<'a>( 90*e1997b9aSAndroid Build Coastguard Worker &self, 91*e1997b9aSAndroid Build Coastguard Worker key: &[u8], 92*e1997b9aSAndroid Build Coastguard Worker data: &[u8], 93*e1997b9aSAndroid Build Coastguard Worker aad: Option<&'a [u8]>, 94*e1997b9aSAndroid Build Coastguard Worker nonce: &[u8], 95*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Vec<u8>, AeadError> { 96*e1997b9aSAndroid Build Coastguard Worker if data.is_empty() { 97*e1997b9aSAndroid Build Coastguard Worker return Err(AeadError::EmptyPlaintext); 98*e1997b9aSAndroid Build Coastguard Worker } 99*e1997b9aSAndroid Build Coastguard Worker if key.len() != self.key_size() { 100*e1997b9aSAndroid Build Coastguard Worker return Err(AeadError::InvalidKeyLen { len: key.len(), expected_len: self.key_size() }); 101*e1997b9aSAndroid Build Coastguard Worker } 102*e1997b9aSAndroid Build Coastguard Worker if nonce.len() != self.nonce_size() { 103*e1997b9aSAndroid Build Coastguard Worker return Err(AeadError::InvalidNonceLen { 104*e1997b9aSAndroid Build Coastguard Worker len: nonce.len(), 105*e1997b9aSAndroid Build Coastguard Worker expected_len: self.nonce_size(), 106*e1997b9aSAndroid Build Coastguard Worker }); 107*e1997b9aSAndroid Build Coastguard Worker } 108*e1997b9aSAndroid Build Coastguard Worker 109*e1997b9aSAndroid Build Coastguard Worker let nonce_array = nonce[..self.nonce_size()].try_into()?; 110*e1997b9aSAndroid Build Coastguard Worker 111*e1997b9aSAndroid Build Coastguard Worker match self.0 { 112*e1997b9aSAndroid Build Coastguard Worker AeadId::Aes128Gcm => { 113*e1997b9aSAndroid Build Coastguard Worker let cipher = Aes128Gcm::new(key[..self.key_size()].try_into()?); 114*e1997b9aSAndroid Build Coastguard Worker Ok(cipher.seal(nonce_array, data, aad.unwrap_or_default())) 115*e1997b9aSAndroid Build Coastguard Worker } 116*e1997b9aSAndroid Build Coastguard Worker AeadId::Aes256Gcm => { 117*e1997b9aSAndroid Build Coastguard Worker let cipher = Aes256Gcm::new(key[..self.key_size()].try_into()?); 118*e1997b9aSAndroid Build Coastguard Worker Ok(cipher.seal(nonce_array, data, aad.unwrap_or_default())) 119*e1997b9aSAndroid Build Coastguard Worker } 120*e1997b9aSAndroid Build Coastguard Worker AeadId::Chacha20Poly1305 => { 121*e1997b9aSAndroid Build Coastguard Worker let cipher = Chacha20Poly1305::new(key[..self.key_size()].try_into()?); 122*e1997b9aSAndroid Build Coastguard Worker Ok(cipher.seal(nonce_array, data, aad.unwrap_or_default())) 123*e1997b9aSAndroid Build Coastguard Worker } 124*e1997b9aSAndroid Build Coastguard Worker _ => Err(AeadError::UnsupportedCipherSuite), 125*e1997b9aSAndroid Build Coastguard Worker } 126*e1997b9aSAndroid Build Coastguard Worker } 127*e1997b9aSAndroid Build Coastguard Worker open<'a>( &self, key: &[u8], ciphertext: &[u8], aad: Option<&'a [u8]>, nonce: &[u8], ) -> Result<Vec<u8>, AeadError>128*e1997b9aSAndroid Build Coastguard Worker async fn open<'a>( 129*e1997b9aSAndroid Build Coastguard Worker &self, 130*e1997b9aSAndroid Build Coastguard Worker key: &[u8], 131*e1997b9aSAndroid Build Coastguard Worker ciphertext: &[u8], 132*e1997b9aSAndroid Build Coastguard Worker aad: Option<&'a [u8]>, 133*e1997b9aSAndroid Build Coastguard Worker nonce: &[u8], 134*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Vec<u8>, AeadError> { 135*e1997b9aSAndroid Build Coastguard Worker if ciphertext.len() < AES_TAG_LEN { 136*e1997b9aSAndroid Build Coastguard Worker return Err(AeadError::TooShortCiphertext { 137*e1997b9aSAndroid Build Coastguard Worker len: ciphertext.len(), 138*e1997b9aSAndroid Build Coastguard Worker min_len: AES_TAG_LEN, 139*e1997b9aSAndroid Build Coastguard Worker }); 140*e1997b9aSAndroid Build Coastguard Worker } 141*e1997b9aSAndroid Build Coastguard Worker if key.len() != self.key_size() { 142*e1997b9aSAndroid Build Coastguard Worker return Err(AeadError::InvalidKeyLen { len: key.len(), expected_len: self.key_size() }); 143*e1997b9aSAndroid Build Coastguard Worker } 144*e1997b9aSAndroid Build Coastguard Worker if nonce.len() != self.nonce_size() { 145*e1997b9aSAndroid Build Coastguard Worker return Err(AeadError::InvalidNonceLen { 146*e1997b9aSAndroid Build Coastguard Worker len: nonce.len(), 147*e1997b9aSAndroid Build Coastguard Worker expected_len: self.nonce_size(), 148*e1997b9aSAndroid Build Coastguard Worker }); 149*e1997b9aSAndroid Build Coastguard Worker } 150*e1997b9aSAndroid Build Coastguard Worker 151*e1997b9aSAndroid Build Coastguard Worker let nonce_array = nonce[..self.nonce_size()].try_into()?; 152*e1997b9aSAndroid Build Coastguard Worker 153*e1997b9aSAndroid Build Coastguard Worker match self.0 { 154*e1997b9aSAndroid Build Coastguard Worker AeadId::Aes128Gcm => { 155*e1997b9aSAndroid Build Coastguard Worker let cipher = Aes128Gcm::new(key[..self.key_size()].try_into()?); 156*e1997b9aSAndroid Build Coastguard Worker cipher 157*e1997b9aSAndroid Build Coastguard Worker .open(nonce_array, ciphertext, aad.unwrap_or_default()) 158*e1997b9aSAndroid Build Coastguard Worker .ok_or(AeadError::InvalidCiphertext) 159*e1997b9aSAndroid Build Coastguard Worker } 160*e1997b9aSAndroid Build Coastguard Worker AeadId::Aes256Gcm => { 161*e1997b9aSAndroid Build Coastguard Worker let cipher = Aes256Gcm::new(key[..self.key_size()].try_into()?); 162*e1997b9aSAndroid Build Coastguard Worker cipher 163*e1997b9aSAndroid Build Coastguard Worker .open(nonce_array, ciphertext, aad.unwrap_or_default()) 164*e1997b9aSAndroid Build Coastguard Worker .ok_or(AeadError::InvalidCiphertext) 165*e1997b9aSAndroid Build Coastguard Worker } 166*e1997b9aSAndroid Build Coastguard Worker AeadId::Chacha20Poly1305 => { 167*e1997b9aSAndroid Build Coastguard Worker let cipher = Chacha20Poly1305::new(key[..self.key_size()].try_into()?); 168*e1997b9aSAndroid Build Coastguard Worker cipher 169*e1997b9aSAndroid Build Coastguard Worker .open(nonce_array, ciphertext, aad.unwrap_or_default()) 170*e1997b9aSAndroid Build Coastguard Worker .ok_or(AeadError::InvalidCiphertext) 171*e1997b9aSAndroid Build Coastguard Worker } 172*e1997b9aSAndroid Build Coastguard Worker _ => Err(AeadError::UnsupportedCipherSuite), 173*e1997b9aSAndroid Build Coastguard Worker } 174*e1997b9aSAndroid Build Coastguard Worker } 175*e1997b9aSAndroid Build Coastguard Worker 176*e1997b9aSAndroid Build Coastguard Worker #[inline(always)] key_size(&self) -> usize177*e1997b9aSAndroid Build Coastguard Worker fn key_size(&self) -> usize { 178*e1997b9aSAndroid Build Coastguard Worker self.0.key_size() 179*e1997b9aSAndroid Build Coastguard Worker } 180*e1997b9aSAndroid Build Coastguard Worker nonce_size(&self) -> usize181*e1997b9aSAndroid Build Coastguard Worker fn nonce_size(&self) -> usize { 182*e1997b9aSAndroid Build Coastguard Worker self.0.nonce_size() 183*e1997b9aSAndroid Build Coastguard Worker } 184*e1997b9aSAndroid Build Coastguard Worker aead_id(&self) -> u16185*e1997b9aSAndroid Build Coastguard Worker fn aead_id(&self) -> u16 { 186*e1997b9aSAndroid Build Coastguard Worker self.0 as u16 187*e1997b9aSAndroid Build Coastguard Worker } 188*e1997b9aSAndroid Build Coastguard Worker } 189*e1997b9aSAndroid Build Coastguard Worker 190*e1997b9aSAndroid Build Coastguard Worker #[cfg(all(not(mls_build_async), test))] 191*e1997b9aSAndroid Build Coastguard Worker mod test { 192*e1997b9aSAndroid Build Coastguard Worker use super::{AeadError, AeadWrapper}; 193*e1997b9aSAndroid Build Coastguard Worker use assert_matches::assert_matches; 194*e1997b9aSAndroid Build Coastguard Worker use mls_rs_core::crypto::CipherSuite; 195*e1997b9aSAndroid Build Coastguard Worker use mls_rs_crypto_traits::{AeadType, AES_TAG_LEN}; 196*e1997b9aSAndroid Build Coastguard Worker get_aeads() -> Vec<AeadWrapper>197*e1997b9aSAndroid Build Coastguard Worker fn get_aeads() -> Vec<AeadWrapper> { 198*e1997b9aSAndroid Build Coastguard Worker [ 199*e1997b9aSAndroid Build Coastguard Worker CipherSuite::CURVE25519_AES128, 200*e1997b9aSAndroid Build Coastguard Worker CipherSuite::CURVE25519_CHACHA, 201*e1997b9aSAndroid Build Coastguard Worker CipherSuite::CURVE448_AES256, 202*e1997b9aSAndroid Build Coastguard Worker ] 203*e1997b9aSAndroid Build Coastguard Worker .into_iter() 204*e1997b9aSAndroid Build Coastguard Worker .map(|suite| AeadWrapper::new(suite).unwrap()) 205*e1997b9aSAndroid Build Coastguard Worker .collect() 206*e1997b9aSAndroid Build Coastguard Worker } 207*e1997b9aSAndroid Build Coastguard Worker 208*e1997b9aSAndroid Build Coastguard Worker #[test] seal_and_open()209*e1997b9aSAndroid Build Coastguard Worker fn seal_and_open() { 210*e1997b9aSAndroid Build Coastguard Worker for aead in get_aeads() { 211*e1997b9aSAndroid Build Coastguard Worker let key = vec![42u8; aead.key_size()]; 212*e1997b9aSAndroid Build Coastguard Worker let nonce = vec![42u8; aead.nonce_size()]; 213*e1997b9aSAndroid Build Coastguard Worker let plaintext = b"message"; 214*e1997b9aSAndroid Build Coastguard Worker 215*e1997b9aSAndroid Build Coastguard Worker let ciphertext = aead.seal(&key, plaintext, None, &nonce).unwrap(); 216*e1997b9aSAndroid Build Coastguard Worker assert_eq!( 217*e1997b9aSAndroid Build Coastguard Worker plaintext, 218*e1997b9aSAndroid Build Coastguard Worker aead.open(&key, ciphertext.as_slice(), None, &nonce).unwrap().as_slice(), 219*e1997b9aSAndroid Build Coastguard Worker "open failed for AEAD with ID {}", 220*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 221*e1997b9aSAndroid Build Coastguard Worker ); 222*e1997b9aSAndroid Build Coastguard Worker } 223*e1997b9aSAndroid Build Coastguard Worker } 224*e1997b9aSAndroid Build Coastguard Worker 225*e1997b9aSAndroid Build Coastguard Worker #[test] seal_and_open_with_invalid_key()226*e1997b9aSAndroid Build Coastguard Worker fn seal_and_open_with_invalid_key() { 227*e1997b9aSAndroid Build Coastguard Worker for aead in get_aeads() { 228*e1997b9aSAndroid Build Coastguard Worker let data = b"top secret data that's long enough"; 229*e1997b9aSAndroid Build Coastguard Worker let nonce = vec![42u8; aead.nonce_size()]; 230*e1997b9aSAndroid Build Coastguard Worker 231*e1997b9aSAndroid Build Coastguard Worker let key_short = vec![42u8; aead.key_size() - 1]; 232*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 233*e1997b9aSAndroid Build Coastguard Worker aead.seal(&key_short, data, None, &nonce), 234*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidKeyLen { .. }), 235*e1997b9aSAndroid Build Coastguard Worker "seal with short key should fail for AEAD with ID {}", 236*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 237*e1997b9aSAndroid Build Coastguard Worker ); 238*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 239*e1997b9aSAndroid Build Coastguard Worker aead.open(&key_short, data, None, &nonce), 240*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidKeyLen { .. }), 241*e1997b9aSAndroid Build Coastguard Worker "open with short key should fail for AEAD with ID {}", 242*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 243*e1997b9aSAndroid Build Coastguard Worker ); 244*e1997b9aSAndroid Build Coastguard Worker 245*e1997b9aSAndroid Build Coastguard Worker let key_long = vec![42u8; aead.key_size() + 1]; 246*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 247*e1997b9aSAndroid Build Coastguard Worker aead.seal(&key_long, data, None, &nonce), 248*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidKeyLen { .. }), 249*e1997b9aSAndroid Build Coastguard Worker "seal with long key should fail for AEAD with ID {}", 250*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 251*e1997b9aSAndroid Build Coastguard Worker ); 252*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 253*e1997b9aSAndroid Build Coastguard Worker aead.open(&key_long, data, None, &nonce), 254*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidKeyLen { .. }), 255*e1997b9aSAndroid Build Coastguard Worker "open with long key should fail for AEAD with ID {}", 256*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 257*e1997b9aSAndroid Build Coastguard Worker ); 258*e1997b9aSAndroid Build Coastguard Worker } 259*e1997b9aSAndroid Build Coastguard Worker } 260*e1997b9aSAndroid Build Coastguard Worker 261*e1997b9aSAndroid Build Coastguard Worker #[test] invalid_ciphertext()262*e1997b9aSAndroid Build Coastguard Worker fn invalid_ciphertext() { 263*e1997b9aSAndroid Build Coastguard Worker for aead in get_aeads() { 264*e1997b9aSAndroid Build Coastguard Worker let key = vec![42u8; aead.key_size()]; 265*e1997b9aSAndroid Build Coastguard Worker let nonce = vec![42u8; aead.nonce_size()]; 266*e1997b9aSAndroid Build Coastguard Worker 267*e1997b9aSAndroid Build Coastguard Worker let ciphertext_short = [0u8; AES_TAG_LEN - 1]; 268*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 269*e1997b9aSAndroid Build Coastguard Worker aead.open(&key, &ciphertext_short, None, &nonce), 270*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::TooShortCiphertext { .. }), 271*e1997b9aSAndroid Build Coastguard Worker "open with short ciphertext should fail for AEAD with ID {}", 272*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 273*e1997b9aSAndroid Build Coastguard Worker ); 274*e1997b9aSAndroid Build Coastguard Worker } 275*e1997b9aSAndroid Build Coastguard Worker } 276*e1997b9aSAndroid Build Coastguard Worker 277*e1997b9aSAndroid Build Coastguard Worker #[test] associated_data_mismatch()278*e1997b9aSAndroid Build Coastguard Worker fn associated_data_mismatch() { 279*e1997b9aSAndroid Build Coastguard Worker for aead in get_aeads() { 280*e1997b9aSAndroid Build Coastguard Worker let key = vec![42u8; aead.key_size()]; 281*e1997b9aSAndroid Build Coastguard Worker let nonce = vec![42u8; aead.nonce_size()]; 282*e1997b9aSAndroid Build Coastguard Worker 283*e1997b9aSAndroid Build Coastguard Worker let ciphertext = aead.seal(&key, b"message", Some(b"foo"), &nonce).unwrap(); 284*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 285*e1997b9aSAndroid Build Coastguard Worker aead.open(&key, &ciphertext, Some(b"bar"), &nonce), 286*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidCiphertext), 287*e1997b9aSAndroid Build Coastguard Worker "open with incorrect associated data should fail for AEAD with ID {}", 288*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 289*e1997b9aSAndroid Build Coastguard Worker ); 290*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 291*e1997b9aSAndroid Build Coastguard Worker aead.open(&key, &ciphertext, None, &nonce), 292*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidCiphertext), 293*e1997b9aSAndroid Build Coastguard Worker "open with incorrect associated data should fail for AEAD with ID {}", 294*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 295*e1997b9aSAndroid Build Coastguard Worker ); 296*e1997b9aSAndroid Build Coastguard Worker } 297*e1997b9aSAndroid Build Coastguard Worker } 298*e1997b9aSAndroid Build Coastguard Worker 299*e1997b9aSAndroid Build Coastguard Worker #[test] invalid_nonce()300*e1997b9aSAndroid Build Coastguard Worker fn invalid_nonce() { 301*e1997b9aSAndroid Build Coastguard Worker for aead in get_aeads() { 302*e1997b9aSAndroid Build Coastguard Worker let key = vec![42u8; aead.key_size()]; 303*e1997b9aSAndroid Build Coastguard Worker let data = b"top secret data that's long enough"; 304*e1997b9aSAndroid Build Coastguard Worker 305*e1997b9aSAndroid Build Coastguard Worker let nonce_short = vec![42u8; aead.nonce_size() - 1]; 306*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 307*e1997b9aSAndroid Build Coastguard Worker aead.seal(&key, data, None, &nonce_short), 308*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidNonceLen { .. }), 309*e1997b9aSAndroid Build Coastguard Worker "seal with short nonce should fail for AEAD with ID {}", 310*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 311*e1997b9aSAndroid Build Coastguard Worker ); 312*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 313*e1997b9aSAndroid Build Coastguard Worker aead.open(&key, data, None, &nonce_short), 314*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidNonceLen { .. }), 315*e1997b9aSAndroid Build Coastguard Worker "open with short nonce should fail for AEAD with ID {}", 316*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 317*e1997b9aSAndroid Build Coastguard Worker ); 318*e1997b9aSAndroid Build Coastguard Worker 319*e1997b9aSAndroid Build Coastguard Worker let nonce_long = vec![42u8; aead.nonce_size() + 1]; 320*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 321*e1997b9aSAndroid Build Coastguard Worker aead.seal(&key, data, None, &nonce_long), 322*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidNonceLen { .. }), 323*e1997b9aSAndroid Build Coastguard Worker "seal with long nonce should fail for AEAD with ID {}", 324*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 325*e1997b9aSAndroid Build Coastguard Worker ); 326*e1997b9aSAndroid Build Coastguard Worker assert_matches!( 327*e1997b9aSAndroid Build Coastguard Worker aead.open(&key, data, None, &nonce_long), 328*e1997b9aSAndroid Build Coastguard Worker Err(AeadError::InvalidNonceLen { .. }), 329*e1997b9aSAndroid Build Coastguard Worker "open with long nonce should fail for AEAD with ID {}", 330*e1997b9aSAndroid Build Coastguard Worker aead.aead_id(), 331*e1997b9aSAndroid Build Coastguard Worker ); 332*e1997b9aSAndroid Build Coastguard Worker } 333*e1997b9aSAndroid Build Coastguard Worker } 334*e1997b9aSAndroid Build Coastguard Worker } 335