From 1fe941bc8161ad646858b92e15b0dcbfae22aa51 Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sat, 15 Jan 2022 19:28:41 +0530 Subject: [PATCH 1/2] Create in-place variants for encrypt_auth/decrypt_auth This is invaluable for embedded systems --- mbedtls/src/cipher/mod.rs | 63 +++++++++++++++++++++++++++++++++ mbedtls/src/cipher/raw/mod.rs | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/mbedtls/src/cipher/mod.rs b/mbedtls/src/cipher/mod.rs index adb2f4aca..920b67c84 100644 --- a/mbedtls/src/cipher/mod.rs +++ b/mbedtls/src/cipher/mod.rs @@ -286,6 +286,20 @@ impl Cipher { self.change_state(), )) } + + pub fn encrypt_auth_inplace( + mut self, + ad: &[u8], + data_and_tag: &mut [u8], + input_len: usize, + tag_len: usize, + ) -> Result<(usize, Cipher)> { + Ok(( + self.raw_cipher + .encrypt_auth_inplace(ad, data_and_tag, input_len, tag_len)?, + self.change_state(), + )) + } } impl Cipher { @@ -302,6 +316,19 @@ impl Cipher { self.change_state(), )) } + + pub fn decrypt_auth_inplace( + mut self, + ad: &[u8], + cipher_text_and_tag: &mut [u8], + tag_len: usize, + ) -> Result<(usize, Cipher)> { + Ok(( + self.raw_cipher + .decrypt_auth_inplace(ad, cipher_text_and_tag, tag_len)?, + self.change_state(), + )) + } } impl Cipher { @@ -401,6 +428,42 @@ fn ccm() { assert_eq!(p, p_out); } +#[test] +fn ccm_inplace() { + // Example vector C.1 + let k = [ + 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 = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; + let mut c = [0x20, 0x21, 0x22, 0x23, 0x0, 0x0, 0x0, 0x0]; + let validate_cipher = [0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d]; + let validate_plain = [0x20, 0x21, 0x22, 0x23]; + + let cipher = Cipher::<_, Authenticated, _>::new( + raw::CipherId::Aes, + raw::CipherMode::CCM, + (k.len() * 8) as _, + ) + .unwrap(); + let cipher = cipher.set_key_iv(&k, &iv).unwrap(); + cipher + .encrypt_auth_inplace(&ad, &mut c, 4, 4) + .unwrap(); + assert_eq!(c, validate_cipher); + + let cipher = Cipher::<_, Authenticated, _>::new( + raw::CipherId::Aes, + raw::CipherMode::CCM, + (k.len() * 8) as _, + ) + .unwrap(); + let cipher = cipher.set_key_iv(&k, &iv).unwrap(); + cipher.decrypt_auth_inplace(&ad, &mut c, 4).unwrap(); + assert_eq!(validate_plain, c[0..4]); +} + #[test] fn aes_kw() { let k = [0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6]; diff --git a/mbedtls/src/cipher/raw/mod.rs b/mbedtls/src/cipher/raw/mod.rs index c39563018..30ddda069 100644 --- a/mbedtls/src/cipher/raw/mod.rs +++ b/mbedtls/src/cipher/raw/mod.rs @@ -387,6 +387,72 @@ impl Cipher { Ok(plain_len) } + pub fn encrypt_auth_inplace( + &mut self, + ad: &[u8], + data_and_tag: &mut [u8], + input_len: usize, + tag_len: usize, + ) -> Result { + if data_and_tag.len() + .checked_sub(tag_len) + .map_or(true, |cipher_len| cipher_len < input_len) { + return Err(Error::CipherBadInputData); + } + + let iv = self.inner.iv; + let iv_len = self.inner.iv_size; + let mut data_and_tag_len = data_and_tag.len(); + unsafe { + cipher_auth_encrypt_ext( + &mut self.inner, + iv.as_ptr(), + iv_len, + ad.as_ptr(), + ad.len(), + data_and_tag.as_ptr(), + input_len, + data_and_tag.as_mut_ptr(), + data_and_tag_len, + &mut data_and_tag_len, + tag_len, + ) + .into_result()? + }; + + Ok(data_and_tag_len) + } + + pub fn decrypt_auth_inplace( + &mut self, + ad: &[u8], + cipher_and_tag: &mut [u8], + tag_len: usize, + ) -> Result { + + let iv = self.inner.iv; + let iv_len = self.inner.iv_size; + let mut plain_len = cipher_and_tag.len(); + unsafe { + cipher_auth_decrypt_ext( + &mut self.inner, + iv.as_ptr(), + iv_len, + ad.as_ptr(), + ad.len(), + cipher_and_tag.as_ptr(), + cipher_and_tag.len(), + cipher_and_tag.as_mut_ptr(), + plain_len, + &mut plain_len, + tag_len, + ) + .into_result()? + }; + + Ok(plain_len) + } + fn do_crypto(&mut self, indata: &[u8], outdata: &mut [u8]) -> Result { self.reset()?; From 98e59cf5b0c19a5319b8b8e0cf30d81bc786d9e8 Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sat, 5 Feb 2022 16:43:07 +0530 Subject: [PATCH 2/2] Pass a separate tag, so the data len isn't variable --- mbedtls/src/cipher/mod.rs | 21 ++++++++-------- mbedtls/src/cipher/raw/mod.rs | 46 +++++++++++++++-------------------- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/mbedtls/src/cipher/mod.rs b/mbedtls/src/cipher/mod.rs index 920b67c84..ec133d431 100644 --- a/mbedtls/src/cipher/mod.rs +++ b/mbedtls/src/cipher/mod.rs @@ -290,13 +290,12 @@ impl Cipher { pub fn encrypt_auth_inplace( mut self, ad: &[u8], - data_and_tag: &mut [u8], - input_len: usize, - tag_len: usize, + data: &mut [u8], + tag: &mut [u8], ) -> Result<(usize, Cipher)> { Ok(( self.raw_cipher - .encrypt_auth_inplace(ad, data_and_tag, input_len, tag_len)?, + .encrypt_auth_inplace(ad, data, tag)?, self.change_state(), )) } @@ -320,12 +319,12 @@ impl Cipher { pub fn decrypt_auth_inplace( mut self, ad: &[u8], - cipher_text_and_tag: &mut [u8], - tag_len: usize, + data: &mut [u8], + tag: &[u8], ) -> Result<(usize, Cipher)> { Ok(( self.raw_cipher - .decrypt_auth_inplace(ad, cipher_text_and_tag, tag_len)?, + .decrypt_auth_inplace(ad, data, tag)?, self.change_state(), )) } @@ -448,8 +447,9 @@ fn ccm_inplace() { ) .unwrap(); let cipher = cipher.set_key_iv(&k, &iv).unwrap(); + let (data, tag) = c.split_at_mut(4); cipher - .encrypt_auth_inplace(&ad, &mut c, 4, 4) + .encrypt_auth_inplace(&ad, data, tag) .unwrap(); assert_eq!(c, validate_cipher); @@ -460,8 +460,9 @@ fn ccm_inplace() { ) .unwrap(); let cipher = cipher.set_key_iv(&k, &iv).unwrap(); - cipher.decrypt_auth_inplace(&ad, &mut c, 4).unwrap(); - assert_eq!(validate_plain, c[0..4]); + let (data, tag) = c.split_at_mut(4); + cipher.decrypt_auth_inplace(&ad, data, tag).unwrap(); + assert_eq!(validate_plain, data); } #[test] diff --git a/mbedtls/src/cipher/raw/mod.rs b/mbedtls/src/cipher/raw/mod.rs index 30ddda069..de78643fd 100644 --- a/mbedtls/src/cipher/raw/mod.rs +++ b/mbedtls/src/cipher/raw/mod.rs @@ -390,62 +390,56 @@ impl Cipher { pub fn encrypt_auth_inplace( &mut self, ad: &[u8], - data_and_tag: &mut [u8], - input_len: usize, - tag_len: usize, + data: &mut [u8], + tag: &mut [u8], ) -> Result { - if data_and_tag.len() - .checked_sub(tag_len) - .map_or(true, |cipher_len| cipher_len < input_len) { - return Err(Error::CipherBadInputData); - } let iv = self.inner.iv; let iv_len = self.inner.iv_size; - let mut data_and_tag_len = data_and_tag.len(); + let mut olen = data.len(); unsafe { - cipher_auth_encrypt_ext( + cipher_auth_encrypt( &mut self.inner, iv.as_ptr(), iv_len, ad.as_ptr(), ad.len(), - data_and_tag.as_ptr(), - input_len, - data_and_tag.as_mut_ptr(), - data_and_tag_len, - &mut data_and_tag_len, - tag_len, + data.as_ptr(), + data.len(), + data.as_mut_ptr(), + &mut olen, + tag.as_mut_ptr(), + tag.len(), ) .into_result()? }; - Ok(data_and_tag_len) + Ok(olen) } pub fn decrypt_auth_inplace( &mut self, ad: &[u8], - cipher_and_tag: &mut [u8], - tag_len: usize, + data: &mut [u8], + tag: &[u8], ) -> Result { let iv = self.inner.iv; let iv_len = self.inner.iv_size; - let mut plain_len = cipher_and_tag.len(); + let mut plain_len = data.len(); unsafe { - cipher_auth_decrypt_ext( + cipher_auth_decrypt( &mut self.inner, iv.as_ptr(), iv_len, ad.as_ptr(), ad.len(), - cipher_and_tag.as_ptr(), - cipher_and_tag.len(), - cipher_and_tag.as_mut_ptr(), - plain_len, + data.as_ptr(), + data.len(), + data.as_mut_ptr(), &mut plain_len, - tag_len, + tag.as_ptr(), + tag.len(), ) .into_result()? };