Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions aes-gcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -115,6 +113,12 @@ pub type Nonce<NonceSize> = Array<u8, NonceSize>;
/// AES-GCM tags.
pub type Tag<TagSize = U16> = Array<u8, TagSize>;

/// 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<T: private::SealedNonceSize> 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].
Expand All @@ -125,7 +129,16 @@ pub trait TagSize: private::SealedTagSize {}
impl<T: private::SealedTagSize> 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<T> 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 {}
Expand Down Expand Up @@ -167,7 +180,7 @@ type Ctr32BE<Aes> = ctr::CtrCore<Aes, ctr::flavors::Ctr32BE>;
/// 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
Expand All @@ -176,6 +189,14 @@ type Ctr32BE<Aes> = ctr::CtrCore<Aes, ctr::flavors::Ctr32BE>;
///
/// 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::<Aes128, U0>::new(&key);
/// ```
///
/// # ⚠️ WARNING: Hazmat!
///
/// When using short authentication tags, namely 32-bit tags with `typenum::U4` or
Expand All @@ -186,6 +207,7 @@ type Ctr32BE<Aes> = ctr::CtrCore<Aes, ctr::flavors::Ctr32BE>;
#[derive(Clone)]
pub struct AesGcm<Aes, NonceSize, TagSize = U16>
where
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
/// Encryption cipher.
Expand All @@ -204,6 +226,7 @@ where
impl<Aes, NonceSize, TagSize> KeySizeUser for AesGcm<Aes, NonceSize, TagSize>
where
Aes: KeySizeUser,
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
type KeySize = Aes::KeySize;
Expand All @@ -212,6 +235,7 @@ where
impl<Aes, NonceSize, TagSize> KeyInit for AesGcm<Aes, NonceSize, TagSize>
where
Aes: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit,
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
fn new(key: &Key<Self>) -> Self {
Expand All @@ -222,6 +246,7 @@ where
impl<Aes, NonceSize, TagSize> From<Aes> for AesGcm<Aes, NonceSize, TagSize>
where
Aes: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt,
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
fn from(cipher: Aes) -> Self {
Expand All @@ -244,7 +269,7 @@ where

impl<Aes, NonceSize, TagSize> AeadCore for AesGcm<Aes, NonceSize, TagSize>
where
NonceSize: ArraySize,
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
type NonceSize = NonceSize;
Expand All @@ -255,7 +280,7 @@ where
impl<Aes, NonceSize, TagSize> AeadInOut for AesGcm<Aes, NonceSize, TagSize>
where
Aes: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt,
NonceSize: ArraySize,
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
fn encrypt_inout_detached(
Expand Down Expand Up @@ -310,7 +335,7 @@ where
impl<Aes, NonceSize, TagSize> AesGcm<Aes, NonceSize, TagSize>
where
Aes: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt,
NonceSize: ArraySize,
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
/// Initialize counter mode.
Expand Down Expand Up @@ -370,6 +395,7 @@ where

impl<Aes, NonceSize, TagSize> fmt::Debug for AesGcm<Aes, NonceSize, TagSize>
where
NonceSize: crate::NonceSize,
TagSize: crate::TagSize,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -384,6 +410,7 @@ where
impl<Aes, NonceSize, TagSize> zeroize::ZeroizeOnDrop for AesGcm<Aes, NonceSize, TagSize>
where
Aes: zeroize::ZeroizeOnDrop,
NonceSize: self::NonceSize,
TagSize: self::TagSize,
{
}