From 3147ed203d52a9e3637ab6692bb146a12dccebca Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Wed, 11 Sep 2024 01:11:52 +0900 Subject: [PATCH 1/2] fix(ext/node): validate input length in Cipheriv and Decipheriv --- ext/node/ops/crypto/cipher.rs | 15 ++++++ ext/node/ops/crypto/mod.rs | 20 +++----- tests/unit_node/crypto/crypto_cipher_test.ts | 52 ++++++++++++++++++++ 3 files changed, 73 insertions(+), 14 deletions(-) diff --git a/ext/node/ops/crypto/cipher.rs b/ext/node/ops/crypto/cipher.rs index 94bd5780eb409f..b80aa33fe8352f 100644 --- a/ext/node/ops/crypto/cipher.rs +++ b/ext/node/ops/crypto/cipher.rs @@ -4,6 +4,7 @@ use aes::cipher::block_padding::Pkcs7; use aes::cipher::BlockDecryptMut; use aes::cipher::BlockEncryptMut; use aes::cipher::KeyIvInit; +use deno_core::error::range_error; use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::Resource; @@ -157,6 +158,13 @@ impl Cipher { Aes256Gcm(Box::new(cipher)) } "aes256" | "aes-256-cbc" => { + if key.len() != 32 { + return Err(range_error("Invalid key length")); + } + if iv.len() != 16 { + return Err(type_error("Invalid initialization vector")); + } + Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into()))) } _ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))), @@ -346,6 +354,13 @@ impl Decipher { Aes256Gcm(Box::new(decipher)) } "aes256" | "aes-256-cbc" => { + if key.len() != 32 { + return Err(range_error("Invalid key length")); + } + if iv.len() != 16 { + return Err(type_error("Invalid initialization vector")); + } + Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into()))) } _ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))), diff --git a/ext/node/ops/crypto/mod.rs b/ext/node/ops/crypto/mod.rs index 7384375773c454..600d315587167e 100644 --- a/ext/node/ops/crypto/mod.rs +++ b/ext/node/ops/crypto/mod.rs @@ -220,13 +220,9 @@ pub fn op_node_create_cipheriv( #[string] algorithm: &str, #[buffer] key: &[u8], #[buffer] iv: &[u8], -) -> u32 { - state.resource_table.add( - match cipher::CipherContext::new(algorithm, key, iv) { - Ok(context) => context, - Err(_) => return 0, - }, - ) +) -> Result { + let context = cipher::CipherContext::new(algorithm, key, iv)?; + Ok(state.resource_table.add(context)) } #[op2(fast)] @@ -292,13 +288,9 @@ pub fn op_node_create_decipheriv( #[string] algorithm: &str, #[buffer] key: &[u8], #[buffer] iv: &[u8], -) -> u32 { - state.resource_table.add( - match cipher::DecipherContext::new(algorithm, key, iv) { - Ok(context) => context, - Err(_) => return 0, - }, - ) +) -> Result { + let context = cipher::DecipherContext::new(algorithm, key, iv)?; + Ok(state.resource_table.add(context)) } #[op2(fast)] diff --git a/tests/unit_node/crypto/crypto_cipher_test.ts b/tests/unit_node/crypto/crypto_cipher_test.ts index 91227cf0060e4a..3d22909753d601 100644 --- a/tests/unit_node/crypto/crypto_cipher_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_test.ts @@ -245,6 +245,32 @@ Deno.test({ }, }); +Deno.test({ + name: "createCipheriv - invalid inputs", + fn() { + assertThrows( + () => crypto.createCipheriv("aes256", new Uint8Array(31), new Uint8Array(16)), + RangeError, + "Invalid key length", + ); + assertThrows( + () => crypto.createCipheriv("aes-256-cbc", new Uint8Array(31), new Uint8Array(16)), + RangeError, + "Invalid key length", + ); + assertThrows( + () => crypto.createCipheriv("aes256", new Uint8Array(32), new Uint8Array(15)), + TypeError, + "Invalid initialization vector", + ); + assertThrows( + () => crypto.createCipheriv("aes-256-cbc", new Uint8Array(32), new Uint8Array(15)), + TypeError, + "Invalid initialization vector", + ); + }, +}); + Deno.test({ name: "createDecipheriv - invalid algorithm", fn() { @@ -257,6 +283,32 @@ Deno.test({ }, }); +Deno.test({ + name: "createDecipheriv - invalid inputs", + fn() { + assertThrows( + () => crypto.createDecipheriv("aes256", new Uint8Array(31), new Uint8Array(16)), + RangeError, + "Invalid key length", + ); + assertThrows( + () => crypto.createDecipheriv("aes-256-cbc", new Uint8Array(31), new Uint8Array(16)), + RangeError, + "Invalid key length", + ); + assertThrows( + () => crypto.createDecipheriv("aes256", new Uint8Array(32), new Uint8Array(15)), + TypeError, + "Invalid initialization vector", + ); + assertThrows( + () => crypto.createDecipheriv("aes-256-cbc", new Uint8Array(32), new Uint8Array(15)), + TypeError, + "Invalid initialization vector", + ); + }, +}) + Deno.test({ name: "getCiphers", fn() { From 6bd75d68c0cd0682029c98254eb6f15d873b81b8 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Wed, 11 Sep 2024 12:00:10 +0900 Subject: [PATCH 2/2] fmt --- tests/unit_node/crypto/crypto_cipher_test.ts | 50 ++++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/tests/unit_node/crypto/crypto_cipher_test.ts b/tests/unit_node/crypto/crypto_cipher_test.ts index 3d22909753d601..ad424e5d4eb12f 100644 --- a/tests/unit_node/crypto/crypto_cipher_test.ts +++ b/tests/unit_node/crypto/crypto_cipher_test.ts @@ -249,22 +249,34 @@ Deno.test({ name: "createCipheriv - invalid inputs", fn() { assertThrows( - () => crypto.createCipheriv("aes256", new Uint8Array(31), new Uint8Array(16)), + () => + crypto.createCipheriv("aes256", new Uint8Array(31), new Uint8Array(16)), RangeError, "Invalid key length", ); assertThrows( - () => crypto.createCipheriv("aes-256-cbc", new Uint8Array(31), new Uint8Array(16)), + () => + crypto.createCipheriv( + "aes-256-cbc", + new Uint8Array(31), + new Uint8Array(16), + ), RangeError, "Invalid key length", ); assertThrows( - () => crypto.createCipheriv("aes256", new Uint8Array(32), new Uint8Array(15)), + () => + crypto.createCipheriv("aes256", new Uint8Array(32), new Uint8Array(15)), TypeError, "Invalid initialization vector", ); assertThrows( - () => crypto.createCipheriv("aes-256-cbc", new Uint8Array(32), new Uint8Array(15)), + () => + crypto.createCipheriv( + "aes-256-cbc", + new Uint8Array(32), + new Uint8Array(15), + ), TypeError, "Invalid initialization vector", ); @@ -287,27 +299,47 @@ Deno.test({ name: "createDecipheriv - invalid inputs", fn() { assertThrows( - () => crypto.createDecipheriv("aes256", new Uint8Array(31), new Uint8Array(16)), + () => + crypto.createDecipheriv( + "aes256", + new Uint8Array(31), + new Uint8Array(16), + ), RangeError, "Invalid key length", ); assertThrows( - () => crypto.createDecipheriv("aes-256-cbc", new Uint8Array(31), new Uint8Array(16)), + () => + crypto.createDecipheriv( + "aes-256-cbc", + new Uint8Array(31), + new Uint8Array(16), + ), RangeError, "Invalid key length", ); assertThrows( - () => crypto.createDecipheriv("aes256", new Uint8Array(32), new Uint8Array(15)), + () => + crypto.createDecipheriv( + "aes256", + new Uint8Array(32), + new Uint8Array(15), + ), TypeError, "Invalid initialization vector", ); assertThrows( - () => crypto.createDecipheriv("aes-256-cbc", new Uint8Array(32), new Uint8Array(15)), + () => + crypto.createDecipheriv( + "aes-256-cbc", + new Uint8Array(32), + new Uint8Array(15), + ), TypeError, "Invalid initialization vector", ); }, -}) +}); Deno.test({ name: "getCiphers",