From 0d1beed2e3633d71d5e288e0382b85be361ec13d Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Thu, 8 Aug 2024 06:04:10 -0700 Subject: fix(ext/node): add `CipherIv.setAutoPadding()` (#24940) Co-Authored-By: Luca Casonato Fixes https://github.com/denoland/deno/issues/21804 Ref https://github.com/denoland/deno/issues/20924 --------- Signed-off-by: Divy Srivastava Co-authored-by: Luca Casonato --- ext/node/ops/crypto/cipher.rs | 123 +++++++++++++++++++++++++++++++++++------- 1 file changed, 104 insertions(+), 19 deletions(-) (limited to 'ext/node/ops/crypto/cipher.rs') diff --git a/ext/node/ops/crypto/cipher.rs b/ext/node/ops/crypto/cipher.rs index 1072cc8c0..0c1218d31 100644 --- a/ext/node/ops/crypto/cipher.rs +++ b/ext/node/ops/crypto/cipher.rs @@ -7,6 +7,7 @@ use aes::cipher::KeyIvInit; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::Resource; +use digest::generic_array::GenericArray; use digest::KeyInit; use std::borrow::Cow; @@ -65,13 +66,14 @@ impl CipherContext { pub fn r#final( self, + auto_pad: bool, input: &[u8], output: &mut [u8], ) -> Result { Rc::try_unwrap(self.cipher) .map_err(|_| type_error("Cipher context is already in use"))? .into_inner() - .r#final(input, output) + .r#final(auto_pad, input, output) } } @@ -92,6 +94,7 @@ impl DecipherContext { pub fn r#final( self, + auto_pad: bool, input: &[u8], output: &mut [u8], auth_tag: &[u8], @@ -99,7 +102,7 @@ impl DecipherContext { Rc::try_unwrap(self.decipher) .map_err(|_| type_error("Decipher context is already in use"))? .into_inner() - .r#final(input, output, auth_tag) + .r#final(auto_pad, input, output, auth_tag) } } @@ -209,42 +212,82 @@ impl Cipher { } /// r#final encrypts the last block of the input data. - fn r#final(self, input: &[u8], output: &mut [u8]) -> Result { + fn r#final( + self, + auto_pad: bool, + input: &[u8], + output: &mut [u8], + ) -> Result { assert!(input.len() < 16); use Cipher::*; - match self { - Aes128Cbc(encryptor) => { + match (self, auto_pad) { + (Aes128Cbc(encryptor), true) => { let _ = (*encryptor) .encrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot pad the input data"))?; Ok(None) } - Aes128Ecb(encryptor) => { + (Aes128Cbc(mut encryptor), false) => { + encryptor.encrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(None) + } + (Aes128Ecb(encryptor), true) => { let _ = (*encryptor) .encrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot pad the input data"))?; Ok(None) } - Aes192Ecb(encryptor) => { + (Aes128Ecb(mut encryptor), false) => { + encryptor.encrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(None) + } + (Aes192Ecb(encryptor), true) => { let _ = (*encryptor) .encrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot pad the input data"))?; Ok(None) } - Aes256Ecb(encryptor) => { + (Aes192Ecb(mut encryptor), false) => { + encryptor.encrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(None) + } + (Aes256Ecb(encryptor), true) => { let _ = (*encryptor) .encrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot pad the input data"))?; Ok(None) } - Aes128Gcm(cipher) => Ok(Some(cipher.finish().to_vec())), - Aes256Gcm(cipher) => Ok(Some(cipher.finish().to_vec())), - Aes256Cbc(encryptor) => { + (Aes256Ecb(mut encryptor), false) => { + encryptor.encrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(None) + } + (Aes128Gcm(cipher), _) => Ok(Some(cipher.finish().to_vec())), + (Aes256Gcm(cipher), _) => Ok(Some(cipher.finish().to_vec())), + (Aes256Cbc(encryptor), true) => { let _ = (*encryptor) .encrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot pad the input data"))?; Ok(None) } + (Aes256Cbc(mut encryptor), false) => { + encryptor.encrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(None) + } } } } @@ -345,41 +388,70 @@ impl Decipher { /// r#final decrypts the last block of the input data. fn r#final( self, + auto_pad: bool, input: &[u8], output: &mut [u8], auth_tag: &[u8], ) -> Result<(), AnyError> { use Decipher::*; - match self { - Aes128Cbc(decryptor) => { + match (self, auto_pad) { + (Aes128Cbc(decryptor), true) => { assert!(input.len() == 16); let _ = (*decryptor) .decrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot unpad the input data"))?; Ok(()) } - Aes128Ecb(decryptor) => { + (Aes128Cbc(mut decryptor), false) => { + decryptor.decrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(()) + } + (Aes128Ecb(decryptor), true) => { assert!(input.len() == 16); let _ = (*decryptor) .decrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot unpad the input data"))?; Ok(()) } - Aes192Ecb(decryptor) => { + (Aes128Ecb(mut decryptor), false) => { + decryptor.decrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(()) + } + (Aes192Ecb(decryptor), true) => { assert!(input.len() == 16); let _ = (*decryptor) .decrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot unpad the input data"))?; Ok(()) } - Aes256Ecb(decryptor) => { + (Aes192Ecb(mut decryptor), false) => { + decryptor.decrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(()) + } + (Aes256Ecb(decryptor), true) => { assert!(input.len() == 16); let _ = (*decryptor) .decrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot unpad the input data"))?; Ok(()) } - Aes128Gcm(decipher) => { + (Aes256Ecb(mut decryptor), false) => { + decryptor.decrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(()) + } + (Aes128Gcm(decipher), true) => { let tag = decipher.finish(); if tag.as_slice() == auth_tag { Ok(()) @@ -387,7 +459,10 @@ impl Decipher { Err(type_error("Failed to authenticate data")) } } - Aes256Gcm(decipher) => { + (Aes128Gcm(_), false) => Err(type_error( + "setAutoPadding(false) not supported for Aes256Gcm yet", + )), + (Aes256Gcm(decipher), true) => { let tag = decipher.finish(); if tag.as_slice() == auth_tag { Ok(()) @@ -395,13 +470,23 @@ impl Decipher { Err(type_error("Failed to authenticate data")) } } - Aes256Cbc(decryptor) => { + (Aes256Gcm(_), false) => Err(type_error( + "setAutoPadding(false) not supported for Aes256Gcm yet", + )), + (Aes256Cbc(decryptor), true) => { assert!(input.len() == 16); let _ = (*decryptor) .decrypt_padded_b2b_mut::(input, output) .map_err(|_| type_error("Cannot unpad the input data"))?; Ok(()) } + (Aes256Cbc(mut decryptor), false) => { + decryptor.decrypt_block_b2b_mut( + GenericArray::from_slice(input), + GenericArray::from_mut_slice(output), + ); + Ok(()) + } } } } -- cgit v1.2.3