diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/crypto/00_crypto.js | 18 | ||||
-rw-r--r-- | ext/crypto/decrypt.rs | 108 | ||||
-rw-r--r-- | ext/crypto/encrypt.rs | 79 |
3 files changed, 127 insertions, 78 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 8203a5307..ed179a313 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -664,8 +664,13 @@ ); } - // 3. We only support 96-bit nonce for now. - if (normalizedAlgorithm.iv.byteLength !== 12) { + // 3. We only support 96-bit and 128-bit nonce. + if ( + ArrayPrototypeIncludes( + [12, 16], + normalizedAlgorithm.iv.byteLength, + ) === undefined + ) { throw new DOMException( "Initialization vector length not supported", "NotSupportedError", @@ -3782,8 +3787,13 @@ } // 2. - // We only support 96-bit nonce for now. - if (normalizedAlgorithm.iv.byteLength !== 12) { + // We only support 96-bit and 128-bit nonce. + if ( + ArrayPrototypeIncludes( + [12, 16], + normalizedAlgorithm.iv.byteLength, + ) === undefined + ) { throw new DOMException( "Initialization vector length not supported", "NotSupportedError", diff --git a/ext/crypto/decrypt.rs b/ext/crypto/decrypt.rs index 40dd3a5b5..801e72ea0 100644 --- a/ext/crypto/decrypt.rs +++ b/ext/crypto/decrypt.rs @@ -2,14 +2,15 @@ use std::cell::RefCell; use std::rc::Rc; use crate::shared::*; -use aes::cipher::generic_array::GenericArray; -use aes::Aes192; use aes::BlockEncrypt; use aes::NewBlockCipher; -use aes_gcm::AeadCore; +use aes_gcm::aead::generic_array::typenum::U12; +use aes_gcm::aead::generic_array::typenum::U16; +use aes_gcm::aead::generic_array::ArrayLength; +use aes_gcm::aes::Aes128; +use aes_gcm::aes::Aes192; +use aes_gcm::aes::Aes256; use aes_gcm::AeadInPlace; -use aes_gcm::Aes128Gcm; -use aes_gcm::Aes256Gcm; use aes_gcm::NewAead; use aes_gcm::Nonce; use block_modes::BlockMode; @@ -25,7 +26,6 @@ use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::OpState; use deno_core::ZeroCopyBuf; -use elliptic_curve::consts::U12; use rsa::pkcs1::FromRsaPrivateKey; use rsa::PaddingScheme; use serde::Deserialize; @@ -76,8 +76,6 @@ pub enum DecryptAlgorithm { }, } -type Aes192Gcm = aes_gcm::AesGcm<Aes192, U12>; - pub async fn op_crypto_decrypt( _state: Rc<RefCell<OpState>>, opts: DecryptOptions, @@ -221,26 +219,54 @@ where Ok(plaintext) } -fn decrypt_aes_gcm_gen<B>( +fn decrypt_aes_gcm_gen<N: ArrayLength<u8>>( key: &[u8], - tag: &GenericArray<u8, <B as AeadCore>::TagSize>, - nonce: &GenericArray<u8, <B as AeadCore>::NonceSize>, + tag: &aes_gcm::Tag, + nonce: &[u8], + length: usize, additional_data: Vec<u8>, plaintext: &mut [u8], -) -> Result<(), AnyError> -where - B: AeadInPlace + NewAead, -{ - let cipher = - B::new_from_slice(key).map_err(|_| operation_error("Decryption failed"))?; - cipher - .decrypt_in_place_detached( - nonce, - additional_data.as_slice(), - plaintext, - tag, - ) - .map_err(|_| operation_error("Decryption failed"))?; +) -> Result<(), AnyError> { + let nonce = Nonce::from_slice(nonce); + match length { + 128 => { + let cipher = aes_gcm::AesGcm::<Aes128, N>::new_from_slice(key) + .map_err(|_| operation_error("Decryption failed"))?; + cipher + .decrypt_in_place_detached( + nonce, + additional_data.as_slice(), + plaintext, + tag, + ) + .map_err(|_| operation_error("Decryption failed"))? + } + 192 => { + let cipher = aes_gcm::AesGcm::<Aes192, N>::new_from_slice(key) + .map_err(|_| operation_error("Decryption failed"))?; + cipher + .decrypt_in_place_detached( + nonce, + additional_data.as_slice(), + plaintext, + tag, + ) + .map_err(|_| operation_error("Decryption failed"))? + } + 256 => { + let cipher = aes_gcm::AesGcm::<Aes256, N>::new_from_slice(key) + .map_err(|_| operation_error("Decryption failed"))?; + cipher + .decrypt_in_place_detached( + nonce, + additional_data.as_slice(), + plaintext, + tag, + ) + .map_err(|_| operation_error("Decryption failed"))? + } + _ => return Err(type_error("invalid length")), + }; Ok(()) } @@ -290,11 +316,6 @@ fn decrypt_aes_gcm( let key = key.as_secret_key()?; let additional_data = additional_data.unwrap_or_default(); - // Fixed 96-bit nonce - if iv.len() != 12 { - return Err(type_error("iv length not equal to 12")); - } - // The `aes_gcm` crate only supports 128 bits tag length. // // Note that encryption won't fail, it instead truncates the tag @@ -303,37 +324,32 @@ fn decrypt_aes_gcm( return Err(type_error("tag length not equal to 128")); } - let nonce = Nonce::from_slice(&iv); - let sep = data.len() - (tag_length / 8); let tag = &data[sep..]; // The actual ciphertext, called plaintext because it is reused in place. let mut plaintext = data[..sep].to_vec(); - match length { - 128 => decrypt_aes_gcm_gen::<Aes128Gcm>( - key, - tag.into(), - nonce, - additional_data, - &mut plaintext, - )?, - 192 => decrypt_aes_gcm_gen::<Aes192Gcm>( + + // Fixed 96-bit or 128-bit nonce + match iv.len() { + 12 => decrypt_aes_gcm_gen::<U12>( key, tag.into(), - nonce, + &iv, + length, additional_data, &mut plaintext, )?, - 256 => decrypt_aes_gcm_gen::<Aes256Gcm>( + 16 => decrypt_aes_gcm_gen::<U16>( key, tag.into(), - nonce, + &iv, + length, additional_data, &mut plaintext, )?, - _ => return Err(type_error("invalid length")), - }; + _ => return Err(type_error("iv length not equal to 12 or 16")), + } Ok(plaintext) } diff --git a/ext/crypto/encrypt.rs b/ext/crypto/encrypt.rs index f1d88438b..63f8af889 100644 --- a/ext/crypto/encrypt.rs +++ b/ext/crypto/encrypt.rs @@ -7,10 +7,12 @@ use aes::cipher::NewCipher; use aes::BlockEncrypt; use aes::NewBlockCipher; use aes_gcm::aead::generic_array::typenum::U12; +use aes_gcm::aead::generic_array::typenum::U16; +use aes_gcm::aead::generic_array::ArrayLength; +use aes_gcm::aes::Aes128; use aes_gcm::aes::Aes192; +use aes_gcm::aes::Aes256; use aes_gcm::AeadInPlace; -use aes_gcm::Aes128Gcm; -use aes_gcm::Aes256Gcm; use aes_gcm::NewAead; use aes_gcm::Nonce; use ctr::Ctr; @@ -183,52 +185,73 @@ fn encrypt_aes_cbc( Ok(ciphertext) } -fn encrypt_aes_gcm( - key: RawKeyData, - length: usize, - tag_length: usize, +fn encrypt_aes_gcm_general<N: ArrayLength<u8>>( + key: &[u8], iv: Vec<u8>, - additional_data: Option<Vec<u8>>, - data: &[u8], -) -> Result<Vec<u8>, AnyError> { - let key = key.as_secret_key()?; - let additional_data = additional_data.unwrap_or_default(); - - // Fixed 96-bit nonce - if iv.len() != 12 { - return Err(type_error("iv length not equal to 12")); - } - - let nonce = Nonce::from_slice(&iv); - - let mut ciphertext = data.to_vec(); + length: usize, + ciphertext: &mut [u8], + additional_data: Vec<u8>, +) -> Result<aes_gcm::Tag, AnyError> { + let nonce = Nonce::<N>::from_slice(&iv); let tag = match length { 128 => { - let cipher = Aes128Gcm::new_from_slice(key) + let cipher = aes_gcm::AesGcm::<Aes128, N>::new_from_slice(key) .map_err(|_| operation_error("Encryption failed"))?; cipher - .encrypt_in_place_detached(nonce, &additional_data, &mut ciphertext) + .encrypt_in_place_detached(nonce, &additional_data, ciphertext) .map_err(|_| operation_error("Encryption failed"))? } 192 => { - type Aes192Gcm = aes_gcm::AesGcm<Aes192, U12>; - - let cipher = Aes192Gcm::new_from_slice(key) + let cipher = aes_gcm::AesGcm::<Aes192, N>::new_from_slice(key) .map_err(|_| operation_error("Encryption failed"))?; cipher - .encrypt_in_place_detached(nonce, &additional_data, &mut ciphertext) + .encrypt_in_place_detached(nonce, &additional_data, ciphertext) .map_err(|_| operation_error("Encryption failed"))? } 256 => { - let cipher = Aes256Gcm::new_from_slice(key) + let cipher = aes_gcm::AesGcm::<Aes256, N>::new_from_slice(key) .map_err(|_| operation_error("Encryption failed"))?; cipher - .encrypt_in_place_detached(nonce, &additional_data, &mut ciphertext) + .encrypt_in_place_detached(nonce, &additional_data, ciphertext) .map_err(|_| operation_error("Encryption failed"))? } _ => return Err(type_error("invalid length")), }; + Ok(tag) +} + +fn encrypt_aes_gcm( + key: RawKeyData, + length: usize, + tag_length: usize, + iv: Vec<u8>, + additional_data: Option<Vec<u8>>, + data: &[u8], +) -> Result<Vec<u8>, AnyError> { + let key = key.as_secret_key()?; + let additional_data = additional_data.unwrap_or_default(); + + let mut ciphertext = data.to_vec(); + // Fixed 96-bit OR 128-bit nonce + let tag = match iv.len() { + 12 => encrypt_aes_gcm_general::<U12>( + key, + iv, + length, + &mut ciphertext, + additional_data, + )?, + 16 => encrypt_aes_gcm_general::<U16>( + key, + iv, + length, + &mut ciphertext, + additional_data, + )?, + _ => return Err(type_error("iv length not equal to 12 or 16")), + }; + // Truncated tag to the specified tag length. // `tag` is fixed to be 16 bytes long and (tag_length / 8) is always <= 16 let tag = &tag[..(tag_length / 8)]; |