diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/openssl/src | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/openssl/src')
-rw-r--r-- | vendor/openssl/src/cipher_ctx.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/vendor/openssl/src/cipher_ctx.rs b/vendor/openssl/src/cipher_ctx.rs index 211c58ba2..216c09e5b 100644 --- a/vendor/openssl/src/cipher_ctx.rs +++ b/vendor/openssl/src/cipher_ctx.rs @@ -591,6 +591,50 @@ impl CipherCtxRef { Ok(len) } + /// Like [`Self::cipher_update`] except that it writes output into the + /// `data` buffer. The `inlen` parameter specifies the number of bytes in + /// `data` that are considered the input. For streaming ciphers, the size of + /// `data` must be at least the input size. Otherwise, it must be at least + /// an additional block size larger. + /// + /// Note: Use [`Self::cipher_update`] with no output argument to write AAD. + /// + /// # Panics + /// + /// This function panics if the input size cannot be represented as `int` or + /// exceeds the buffer size, or if the output buffer does not contain enough + /// additional space. + #[corresponds(EVP_CipherUpdate)] + pub fn cipher_update_inplace( + &mut self, + data: &mut [u8], + inlen: usize, + ) -> Result<usize, ErrorStack> { + assert!(inlen <= data.len(), "Input size may not exceed buffer size"); + let block_size = self.block_size(); + if block_size != 1 { + assert!( + data.len() >= inlen + block_size, + "Output buffer size must be at least {} bytes.", + inlen + block_size + ); + } + + let inlen = c_int::try_from(inlen).unwrap(); + let mut outlen = 0; + unsafe { + cvt(ffi::EVP_CipherUpdate( + self.as_ptr(), + data.as_mut_ptr(), + &mut outlen, + data.as_ptr(), + inlen, + )) + }?; + + Ok(outlen as usize) + } + /// Finalizes the encryption or decryption process. /// /// Any remaining data will be written to the output buffer. @@ -778,6 +822,26 @@ mod test { ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); + // encrypt again, but use in-place encryption this time + // First reset the IV + ctx.encrypt_init(None, None, Some(&iv)).unwrap(); + ctx.set_padding(false); + let mut data_inplace: [u8; 32] = [1; 32]; + let outlen = ctx + .cipher_update_inplace(&mut data_inplace[0..15], 15) + .unwrap(); + assert_eq!(15, outlen); + + let outlen = ctx + .cipher_update_inplace(&mut data_inplace[15..32], 17) + .unwrap(); + assert_eq!(17, outlen); + + ctx.cipher_final(&mut [0u8; 0]).unwrap(); + + // Check that the resulting data is encrypted in the same manner + assert_eq!(data_inplace.as_slice(), output.as_slice()); + // try to decrypt ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) .unwrap(); @@ -800,6 +864,19 @@ mod test { ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); // check if the decrypted blocks are the same as input (all ones) assert_eq!(output_decrypted, vec![1; 32]); + + // decrypt again, but now the output in-place + ctx.decrypt_init(None, None, Some(&iv)).unwrap(); + ctx.set_padding(false); + + let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap(); + assert_eq!(15, outlen); + + let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap(); + assert_eq!(17, outlen); + + ctx.cipher_final_vec(&mut vec![0; 0]).unwrap(); + assert_eq!(output_decrypted, output); } #[test] |