diff --git a/mbedtls/src/cipher/mod.rs b/mbedtls/src/cipher/mod.rs index 193d09a4f..53622d845 100644 --- a/mbedtls/src/cipher/mod.rs +++ b/mbedtls/src/cipher/mod.rs @@ -457,3 +457,42 @@ fn aes_kwp() { let out_len = cipher.decrypt_auth(&[], &c, &mut p_out, 0).unwrap().0; assert_eq!(p, &p_out[..out_len]); } + + +#[test] +fn aes_gcm() { + let k = [ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, + 0x4f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, + ]; + let iv = [0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16]; + + let ad = [0x03, 0x04, 0x05]; + let p = [0x20, 0x21, 0x22, 0x23]; + let c = [0x01, 0x08, 0x55, 0x0f]; + let t = [0x3f, 0xd9, 0x8e, 0x74]; + let mut p_out = [0u8; 4]; + let mut c_out = [0u8; 8]; + + let cipher = Cipher::::new( + raw::CipherId::Aes, + raw::CipherMode::GCM, + (k.len() * 8) as _, + ) + .unwrap(); + let cipher = cipher.set_key_iv(&k, &iv).unwrap(); + + cipher.encrypt_auth(&ad, &p, &mut c_out, 4).unwrap(); + assert_eq!(c, c_out[0..4]); + assert_eq!(t, c_out[4..8]); + let cipher = Cipher::<_, Authenticated, _>::new( + raw::CipherId::Aes, + raw::CipherMode::GCM, + (k.len() * 8) as _, + ) + .unwrap(); + let cipher = cipher.set_key_iv(&k, &iv).unwrap(); + cipher.decrypt_auth(&ad, &c_out, &mut p_out, 4).unwrap(); + assert_eq!(p, p_out); +} diff --git a/mbedtls/src/cipher/raw/mod.rs b/mbedtls/src/cipher/raw/mod.rs index 25553af5e..8e414c86d 100644 --- a/mbedtls/src/cipher/raw/mod.rs +++ b/mbedtls/src/cipher/raw/mod.rs @@ -24,6 +24,7 @@ define!( Blowfish = CIPHER_ID_BLOWFISH, Arc4 = CIPHER_ID_ARC4, Aria = CIPHER_ID_ARIA, + Chacha20 = CIPHER_ID_CHACHA20, } ); @@ -39,6 +40,7 @@ impl From for CipherId { CIPHER_ID_BLOWFISH => CipherId::Blowfish, CIPHER_ID_ARC4 => CipherId::Arc4, CIPHER_ID_ARIA => CipherId::Aria, + CIPHER_ID_CHACHA20 => CipherId::Aria, // This should be replaced with TryFrom once it is stable. _ => panic!("Invalid cipher_id_t"), } @@ -58,6 +60,8 @@ define!( GCM = MODE_GCM, STREAM = MODE_STREAM, CCM = MODE_CCM, + XTS = MODE_XTS, + CHACHAPOLY = MODE_CHACHAPOLY, KW = MODE_KW, KWP = MODE_KWP, } @@ -75,6 +79,8 @@ impl From for CipherMode { MODE_GCM => CipherMode::GCM, MODE_STREAM => CipherMode::STREAM, MODE_CCM => CipherMode::CCM, + MODE_XTS => CipherMode::XTS, + MODE_CHACHAPOLY => CipherMode::CHACHAPOLY, MODE_KW => CipherMode::KW, MODE_KWP => CipherMode::KWP, // This should be replaced with TryFrom once it is stable. @@ -135,6 +141,31 @@ define!( Camellia128Ccm = CIPHER_CAMELLIA_128_CCM, Camellia192Ccm = CIPHER_CAMELLIA_192_CCM, Camellia256Ccm = CIPHER_CAMELLIA_256_CCM, + CipherAria128Ecb = CIPHER_ARIA_128_ECB, + CipherAria192Ecb = CIPHER_ARIA_192_ECB, + CipherAria256Ecb = CIPHER_ARIA_256_ECB, + CipherAria128Cbc = CIPHER_ARIA_128_CBC, + CipherAria192Cbc = CIPHER_ARIA_192_CBC, + CipherAria256Cbc = CIPHER_ARIA_256_CBC, + CipherAria128Cfb128 = CIPHER_ARIA_128_CFB128, + CipherAria192Cfb128 = CIPHER_ARIA_192_CFB128, + CipherAria256Cfb128 = CIPHER_ARIA_256_CFB128, + CipherAria128Ctr = CIPHER_ARIA_128_CTR, + CipherAria192Ctr = CIPHER_ARIA_192_CTR, + CipherAria256Ctr = CIPHER_ARIA_256_CTR, + CipherAria128Gcm = CIPHER_ARIA_128_GCM, + CipherAria192Gcm = CIPHER_ARIA_192_GCM, + CipherAria256Gcm = CIPHER_ARIA_256_GCM, + CipherAria128Ccm = CIPHER_ARIA_128_CCM, + CipherAria192Ccm = CIPHER_ARIA_192_CCM, + CipherAria256Ccm = CIPHER_ARIA_256_CCM, + CipherAes128Ofb = CIPHER_AES_128_OFB, + CipherAes192Ofb = CIPHER_AES_192_OFB, + CipherAes256Ofb = CIPHER_AES_256_OFB, + CipherAes128Xts = CIPHER_AES_128_XTS, + CipherAes256Xts = CIPHER_AES_256_XTS, + CipherChacha20 = CIPHER_CHACHA20, + CipherChacha20Poly1305 = CIPHER_CHACHA20_POLY1305, Aes128Kw = CIPHER_AES_128_KW, Aes192Kw = CIPHER_AES_192_KW, Aes256Kw = CIPHER_AES_256_KW, @@ -213,15 +244,15 @@ impl Cipher { unsafe { cipher_update_ad(&mut self.inner, ad.as_ptr(), ad.len()).into_result_discard() } } - pub fn update(&mut self, indata: &[u8], outdata: &mut [u8]) -> Result { - // Check that minimum required space is available in outdata buffer - let reqd_size = if unsafe { *self.inner.cipher_info }.mode == MODE_ECB { + pub fn update(&mut self, in_data: &[u8], out_data: &mut [u8]) -> Result { + // Check that minimum required space is available in out_data buffer + let required_size = if unsafe { *self.inner.cipher_info }.mode == MODE_ECB { self.block_size() } else { - indata.len() + self.block_size() + in_data.len() + self.block_size() }; - if outdata.len() < reqd_size { + if out_data.len() < required_size { return Err(Error::CipherFullBlockExpected); } @@ -229,9 +260,9 @@ impl Cipher { unsafe { cipher_update( &mut self.inner, - indata.as_ptr(), - indata.len(), - outdata.as_mut_ptr(), + in_data.as_ptr(), + in_data.len(), + out_data.as_mut_ptr(), &mut olen, ) .into_result()?; @@ -239,15 +270,15 @@ impl Cipher { Ok(olen) } - pub fn finish(&mut self, outdata: &mut [u8]) -> Result { - // Check that minimum required space is available in outdata buffer - if outdata.len() < self.block_size() { + pub fn finish(&mut self, out_data: &mut [u8]) -> Result { + // Check that minimum required space is available in out_data buffer + if out_data.len() < self.block_size() { return Err(Error::CipherFullBlockExpected); } let mut olen = 0; unsafe { - cipher_finish(&mut self.inner, outdata.as_mut_ptr(), &mut olen).into_result()?; + cipher_finish(&mut self.inner, out_data.as_mut_ptr(), &mut olen).into_result()?; } Ok(olen) } @@ -274,7 +305,7 @@ impl Cipher { unsafe { (*self.inner.cipher_info).mode.into() } } - // Utility function to get mdoe for the selected / setup cipher_info + // Utility function to get mode for the selected / setup cipher_info pub fn is_authenticated(&self) -> bool { unsafe { if (*self.inner.cipher_info).mode == MODE_GCM || (*self.inner.cipher_info).mode == MODE_CCM { @@ -299,7 +330,13 @@ impl Cipher { self.do_crypto(cipher, plain) } - pub fn encrypt_auth(&mut self, ad: &[u8], plain: &[u8], cipher_and_tag: &mut [u8], tag_len: usize) -> Result { + pub fn encrypt_auth( + &mut self, + ad: &[u8], + plain: &[u8], + cipher_and_tag: &mut [u8], + tag_len: usize, + ) -> Result { if cipher_and_tag .len() .checked_sub(tag_len) @@ -365,7 +402,12 @@ impl Cipher { Ok(plain_len) } - pub fn encrypt_auth_inplace(&mut self, ad: &[u8], data: &mut [u8], tag: &mut [u8]) -> Result { + pub fn encrypt_auth_inplace( + &mut self, + ad: &[u8], + data: &mut [u8], + tag: &mut [u8], + ) -> Result { let iv = self.inner.iv; let iv_len = self.inner.iv_size; let mut olen = data.len(); @@ -389,7 +431,12 @@ impl Cipher { Ok(olen) } - pub fn decrypt_auth_inplace(&mut self, ad: &[u8], data: &mut [u8], tag: &[u8]) -> Result { + pub fn decrypt_auth_inplace( + &mut self, + ad: &[u8], + data: &mut [u8], + tag: &[u8], + ) -> Result { let iv = self.inner.iv; let iv_len = self.inner.iv_size; let mut plain_len = data.len(); @@ -413,31 +460,31 @@ impl Cipher { Ok(plain_len) } - fn do_crypto(&mut self, indata: &[u8], outdata: &mut [u8]) -> Result { + fn do_crypto(&mut self, in_data: &[u8], out_data: &mut [u8]) -> Result { self.reset()?; - // The total number of bytes writte to outdata so far. It's safe to + // The total number of bytes written to out_data so far. It's safe to // use this as a start index for slicing: &slice[slice.len()..] will // return an empty slice, it doesn't panic. let mut total_len = 0; if unsafe { *self.inner.cipher_info }.mode == MODE_ECB { // ECB mode requires single-block updates - for chunk in indata.chunks(self.block_size()) { - let len = self.update(chunk, &mut outdata[total_len..])?; + for chunk in in_data.chunks(self.block_size()) { + let len = self.update(chunk, &mut out_data[total_len..])?; total_len += len; } } else { - total_len = self.update(indata, outdata)?; - total_len += self.finish(&mut outdata[total_len..])?; + total_len = self.update(in_data, out_data)?; + total_len += self.finish(&mut out_data[total_len..])?; } Ok(total_len) } - pub fn cmac(&mut self, key: &[u8], data: &[u8], outdata: &mut [u8]) -> Result<()> { - // Check that outdata buffer has enough space - if outdata.len() < self.block_size() { + pub fn cmac(&mut self, key: &[u8], data: &[u8], out_data: &mut [u8]) -> Result<()> { + // Check that out_data buffer has enough space + if out_data.len() < self.block_size() { return Err(Error::CipherFullBlockExpected); } self.reset()?; @@ -448,7 +495,7 @@ impl Cipher { (key.len() * 8) as _, data.as_ptr(), data.len(), - outdata.as_mut_ptr(), + out_data.as_mut_ptr(), ) .into_result()?; } @@ -491,5 +538,8 @@ fn cmac_test() { &mut out, ) .expect("Success in CMAC"); - assert_eq!(&out, b"\x38\x7b\x36\x22\x8b\xa7\x77\x44\x5b\xaf\xa0\x36\x45\xb9\x40\x10"); + assert_eq!( + &out, + b"\x38\x7b\x36\x22\x8b\xa7\x77\x44\x5b\xaf\xa0\x36\x45\xb9\x40\x10" + ); }