diff --git a/aes-gcm/src/lib.rs b/aes-gcm/src/lib.rs index 90c0ca69..da536aa6 100644 --- a/aes-gcm/src/lib.rs +++ b/aes-gcm/src/lib.rs @@ -90,9 +90,7 @@ pub use aes; use aead::{TagPosition, inout::InOutBuf}; use cipher::{ - BlockCipherEncrypt, BlockSizeUser, InnerIvInit, StreamCipherCore, - array::{Array, ArraySize}, - consts::U16, + BlockCipherEncrypt, BlockSizeUser, InnerIvInit, StreamCipherCore, array::Array, consts::U16, }; use core::{fmt, marker::PhantomData}; use ghash::{GHash, universal_hash::UniversalHash}; @@ -115,6 +113,12 @@ pub type Nonce = Array; /// AES-GCM tags. pub type Tag = Array; +/// Trait implemented for valid nonce sizes, i.e. non-zero sizes as required +/// by NIST SP 800-38D Section 5.2.1.1. +pub trait NonceSize: private::SealedNonceSize {} + +impl NonceSize for T {} + /// Trait implemented for valid tag sizes, i.e. /// [`U12`][consts::U12], [`U13`][consts::U13], [`U14`][consts::U14], /// [`U15`][consts::U15] and [`U16`][consts::U16]. @@ -125,7 +129,16 @@ pub trait TagSize: private::SealedTagSize {} impl TagSize for T {} mod private { - use cipher::{array::ArraySize, consts, typenum::Unsigned}; + use cipher::{ + array::ArraySize, + consts, + typenum::{NonZero, Unsigned}, + }; + + // Sealed traits stop other crates from implementing any traits that use it. + pub trait SealedNonceSize: ArraySize + Unsigned {} + + impl SealedNonceSize for T where T: ArraySize + Unsigned + NonZero {} // Sealed traits stop other crates from implementing any traits that use it. pub trait SealedTagSize: ArraySize + Unsigned {} @@ -167,7 +180,7 @@ type Ctr32BE = ctr::CtrCore; /// Doing so runs the risk of unintended cryptographic properties! /// /// The `NonceSize` generic parameter can be used to instantiate AES-GCM with other -/// nonce sizes, however it's recommended to use it with `typenum::U12`, +/// non-zero nonce sizes, however it's recommended to use it with `typenum::U12`, /// the default of 96-bits. /// /// The `TagSize` generic parameter can be used to instantiate AES-GCM with other @@ -176,6 +189,14 @@ type Ctr32BE = ctr::CtrCore; /// /// If in doubt, use the built-in [`Aes128Gcm`] and [`Aes256Gcm`] type aliases. /// +/// Compilation will fail if the nonce size is zero: +/// +/// ```rust,compile_fail +/// # use aes_gcm::{AesGcm, aead::{KeyInit, consts::U0}, aes::Aes128}; +/// # let key = [42; 16].into(); +/// let cipher = AesGcm::::new(&key); +/// ``` +/// /// # ⚠️ WARNING: Hazmat! /// /// When using short authentication tags, namely 32-bit tags with `typenum::U4` or @@ -186,6 +207,7 @@ type Ctr32BE = ctr::CtrCore; #[derive(Clone)] pub struct AesGcm where + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { /// Encryption cipher. @@ -204,6 +226,7 @@ where impl KeySizeUser for AesGcm where Aes: KeySizeUser, + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { type KeySize = Aes::KeySize; @@ -212,6 +235,7 @@ where impl KeyInit for AesGcm where Aes: BlockSizeUser + BlockCipherEncrypt + KeyInit, + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { fn new(key: &Key) -> Self { @@ -222,6 +246,7 @@ where impl From for AesGcm where Aes: BlockSizeUser + BlockCipherEncrypt, + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { fn from(cipher: Aes) -> Self { @@ -244,7 +269,7 @@ where impl AeadCore for AesGcm where - NonceSize: ArraySize, + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { type NonceSize = NonceSize; @@ -255,7 +280,7 @@ where impl AeadInOut for AesGcm where Aes: BlockSizeUser + BlockCipherEncrypt, - NonceSize: ArraySize, + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { fn encrypt_inout_detached( @@ -310,7 +335,7 @@ where impl AesGcm where Aes: BlockSizeUser + BlockCipherEncrypt, - NonceSize: ArraySize, + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { /// Initialize counter mode. @@ -370,6 +395,7 @@ where impl fmt::Debug for AesGcm where + NonceSize: crate::NonceSize, TagSize: crate::TagSize, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -384,6 +410,7 @@ where impl zeroize::ZeroizeOnDrop for AesGcm where Aes: zeroize::ZeroizeOnDrop, + NonceSize: self::NonceSize, TagSize: self::TagSize, { }