diff --git a/botan/src/cipher.rs b/botan/src/cipher.rs index 5e04c26..bf6534d 100644 --- a/botan/src/cipher.rs +++ b/botan/src/cipher.rs @@ -246,9 +246,21 @@ impl Cipher { botan_call!(botan_cipher_start, self.obj, nonce.as_ptr(), nonce.len()) } + /// calculate output length for a message of given size + fn output_length(&self, len: usize, end: bool) -> Result { + let mut out_len = 0; + botan_call!(botan_cipher_output_length, self.obj, len, &mut out_len)?; + let out_len = match (self.direction, end) { + (CipherDirection::Encrypt, true) | (CipherDirection::Decrypt, true) => out_len, + (CipherDirection::Encrypt, false) => out_len.saturating_sub(self.tag_length()), + (CipherDirection::Decrypt, false) => out_len + self.tag_length(), + }; + Ok(out_len) + } + /// incremental update fn _update(&mut self, msg: &[u8], end: bool) -> Result> { - let mut output = vec![0; msg.len() + if end { self.tag_length() } else { 0 }]; + let mut output = vec![0; self.output_length(msg.len(), end)?]; let output_written = self._update_into(msg, end, &mut output)?; output.resize(output_written, 0); Ok(output) @@ -258,11 +270,7 @@ impl Cipher { /// /// Returns the number of bytes written to `output`. fn _update_into(&mut self, msg: &[u8], end: bool, output: &mut [u8]) -> Result { - let expected_len = match (self.direction, end) { - (CipherDirection::Encrypt, false) | (CipherDirection::Decrypt, false) => msg.len(), - (CipherDirection::Encrypt, true) => msg.len() + self.tag_length(), - (CipherDirection::Decrypt, true) => msg.len().saturating_sub(self.tag_length()), - }; + let expected_len = self.output_length(msg.len(), end)?; if output.len() < expected_len { return Err(Error::with_message( diff --git a/botan/tests/tests.rs b/botan/tests/tests.rs index 105423a..7841683 100644 --- a/botan/tests/tests.rs +++ b/botan/tests/tests.rs @@ -305,6 +305,25 @@ fn test_incremental_cipher() -> Result<(), botan::Error> { Ok(()) } +#[test] +fn test_cipher_padding() -> Result<(), botan::Error> { + let mut cipher = botan::Cipher::new("AES-128/CBC/PKCS7", botan::CipherDirection::Encrypt)?; + let key = [0; 16]; + let nonce = [0; 16]; + let msg = [0; 8]; + + cipher.set_key(&key)?; + cipher.start(&nonce)?; + let ct = cipher.finish(&msg)?; + + let mut cipher = botan::Cipher::new("AES-128/CBC/PKCS7", botan::CipherDirection::Decrypt)?; + cipher.set_key(&key)?; + cipher.start(&nonce)?; + assert_eq!(cipher.finish(&ct)?, msg); + + Ok(()) +} + #[test] fn test_chacha() -> Result<(), botan::Error> { let mut cipher = botan::Cipher::new("ChaCha20", botan::CipherDirection::Encrypt)?;