diff --git a/aes-gcm/src/ctr.rs b/aes-gcm/src/ctr.rs index 20be3e9f..e6d63854 100644 --- a/aes-gcm/src/ctr.rs +++ b/aes-gcm/src/ctr.rs @@ -1,7 +1,7 @@ //! Counter mode implementation use block_cipher_trait::generic_array::{ - typenum::{Unsigned, U12, U16}, + typenum::{Unsigned, U16}, ArrayLength, GenericArray, }; use block_cipher_trait::BlockCipher; @@ -35,10 +35,14 @@ where B::ParBlocks: ArrayLength>, { /// Instantiate a new CTR instance - pub fn new(nonce: &GenericArray) -> Self { + pub fn new(nonce: &[u8]) -> Self { let mut counter_block = GenericArray::default(); - counter_block[..12].copy_from_slice(nonce.as_slice()); - counter_block[15] = 1; + if nonce.len() == 12 { + counter_block[..12].copy_from_slice(nonce); + counter_block[15] = 1; + } else { + counter_block[..].copy_from_slice(nonce); + } Self { block_cipher: PhantomData, diff --git a/aes-gcm/src/lib.rs b/aes-gcm/src/lib.rs index 6a928ddf..ee25698f 100644 --- a/aes-gcm/src/lib.rs +++ b/aes-gcm/src/lib.rs @@ -183,13 +183,12 @@ where B: BlockCipher, B::ParBlocks: ArrayLength>, { - type NonceSize = U12; type TagSize = U16; type CiphertextOverhead = U0; fn encrypt_in_place_detached( &self, - nonce: &GenericArray, + nonce: &[u8], associated_data: &[u8], buffer: &mut [u8], ) -> Result { @@ -197,9 +196,19 @@ where return Err(Error); } + // Handles variable-length nonce + let nonce = if nonce.len() != 12 { + let ghash = &mut self.ghash.clone(); + ghash.update_padded(nonce); + let nonce = ghash.result_reset().into_bytes().to_vec(); + nonce + } else { + nonce.to_vec() + }; + // TODO(tarcieri): interleave encryption with GHASH // See: - let mut ctr = Ctr32::new(nonce); + let mut ctr = Ctr32::new(nonce.as_ref()); ctr.seek(1); ctr.apply_keystream(&self.cipher, buffer); @@ -212,7 +221,7 @@ where fn decrypt_in_place_detached( &self, - nonce: &GenericArray, + nonce: &[u8], associated_data: &[u8], buffer: &mut [u8], tag: &Tag, @@ -221,10 +230,20 @@ where return Err(Error); } + // Handles variable-length nonce + let nonce = if nonce.len() != 12 { + let ghash = &mut self.ghash.clone(); + ghash.update_padded(nonce); + let nonce = ghash.result_reset().into_bytes().to_vec(); + nonce + } else { + nonce.to_vec() + }; + // TODO(tarcieri): interleave encryption with GHASH // See: let mut expected_tag = compute_tag(&mut self.ghash.clone(), associated_data, buffer); - let mut ctr = Ctr32::new(nonce); + let mut ctr = Ctr32::new(nonce.as_ref()); ctr.apply_keystream(&self.cipher, expected_tag.as_mut_slice()); use subtle::ConstantTimeEq;