Skip to content

Commit

Permalink
[WIP] aes-gcm: bump aes crate to v0.8
Browse files Browse the repository at this point in the history
TODO: doctests
  • Loading branch information
tarcieri committed Mar 19, 2022
1 parent e1e35e0 commit 5d05d05
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 85 deletions.
44 changes: 32 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions aes-gcm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ categories = ["cryptography", "no-std"]

[dependencies]
aead = { version = "0.4", default-features = false }
aes = { version = "0.7.5", optional = true }
cipher = "0.3"
ctr = "0.8"
aes = { version = "0.8", optional = true }
cipher = "0.4"
ctr = "0.9"
ghash = { version = "0.4.2", default-features = false }
subtle = { version = "2", default-features = false }
zeroize = { version = "1", optional = true, default-features = false }
Expand All @@ -32,8 +32,8 @@ hex-literal = "0.3"
default = ["aes", "alloc"]
std = ["aead/std", "alloc"]
alloc = ["aead/alloc"]
armv8 = ["aes/armv8", "ghash/armv8"] # nightly-only
force-soft = ["aes/force-soft", "ghash/force-soft"]
armv8 = ["ghash/armv8"] # nightly-only
force-soft = ["ghash/force-soft"]
heapless = ["aead/heapless"]
stream = ["aead/stream"]

Expand Down
91 changes: 41 additions & 50 deletions aes-gcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
//!
//! Simple usage (allocating, no associated data):
//!
//! ```
// TODO(tarcieri): fix doctests
//! ```ignore
//! use aes_gcm::{Aes256Gcm, Key, Nonce}; // Or `Aes128Gcm`
//! use aes_gcm::aead::{Aead, NewAead};
//!
Expand Down Expand Up @@ -64,7 +65,8 @@
//! which can then be passed as the `buffer` parameter to the in-place encrypt
//! and decrypt methods:
//!
//! ```
// TODO(tarcieri): fix doctests
//! ```ignore
//! # #[cfg(feature = "heapless")]
//! # {
//! use aes_gcm::{Aes256Gcm, Key, Nonce}; // Or `Aes128Gcm`
Expand Down Expand Up @@ -112,12 +114,10 @@ pub use aes;

use cipher::{
consts::{U0, U16},
generic_array::{typenum::Unsigned, ArrayLength, GenericArray},
Block, BlockCipher, BlockCipherKey, BlockEncrypt, FromBlockCipher, NewBlockCipher,
StreamCipher, StreamCipherSeek,
generic_array::{ArrayLength, GenericArray},
BlockCipher, BlockEncrypt, BlockSizeUser, InnerIvInit, KeyInit, StreamCipherCore,
};
use core::marker::PhantomData;
use ctr::Ctr32BE;
use ghash::{
universal_hash::{NewUniversalHash, UniversalHash},
GHash,
Expand All @@ -138,12 +138,6 @@ pub const P_MAX: u64 = 1 << 36;
/// Maximum length of ciphertext
pub const C_MAX: u64 = (1 << 36) + 16;

/// AES-GCM keys
pub type Key<KeySize> = GenericArray<u8, KeySize>;

/// AES-GCM nonces
pub type Nonce<NonceSize> = GenericArray<u8, NonceSize>;

/// AES-GCM tags
pub type Tag = GenericArray<u8, U16>;

Expand All @@ -157,6 +151,12 @@ pub type Aes128Gcm = AesGcm<Aes128, U12>;
#[cfg_attr(docsrs, doc(cfg(feature = "aes")))]
pub type Aes256Gcm = AesGcm<Aes256, U12>;

/// AES block.
type Block = GenericArray<u8, U16>;

/// Counter mode with a 32-bit big endian counter.
type Ctr32BE<Aes> = ctr::CtrCore<Aes, ctr::flavors::Ctr32BE>;

/// AES-GCM: generic over an underlying AES implementation and nonce size.
///
/// This type is generic to support substituting alternative AES implementations
Expand All @@ -171,12 +171,7 @@ pub type Aes256Gcm = AesGcm<Aes256, U12>;
///
/// If in doubt, use the built-in [`Aes128Gcm`] and [`Aes256Gcm`] type aliases.
#[derive(Clone)]
pub struct AesGcm<Aes, NonceSize>
where
Aes: BlockCipher<BlockSize = U16> + BlockEncrypt,
Aes::ParBlocks: ArrayLength<Block<Aes>>,
NonceSize: ArrayLength<u8>,
{
pub struct AesGcm<Aes, NonceSize> {
/// Encryption cipher
cipher: Aes,

Expand All @@ -189,22 +184,18 @@ where

impl<Aes, NonceSize> NewAead for AesGcm<Aes, NonceSize>
where
Aes: NewBlockCipher + BlockCipher<BlockSize = U16> + BlockEncrypt,
Aes::ParBlocks: ArrayLength<Block<Aes>>,
NonceSize: ArrayLength<u8>,
Aes: BlockSizeUser<BlockSize = U16> + BlockEncrypt + KeyInit,
{
type KeySize = Aes::KeySize;

fn new(key: &BlockCipherKey<Aes>) -> Self {
fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
Aes::new(key).into()
}
}

impl<Aes, NonceSize> From<Aes> for AesGcm<Aes, NonceSize>
where
Aes: NewBlockCipher + BlockCipher<BlockSize = U16> + BlockEncrypt,
Aes::ParBlocks: ArrayLength<Block<Aes>>,
NonceSize: ArrayLength<u8>,
Aes: BlockSizeUser<BlockSize = U16> + BlockEncrypt,
{
fn from(cipher: Aes) -> Self {
let mut ghash_key = ghash::Key::default();
Expand All @@ -225,8 +216,6 @@ where

impl<Aes, NonceSize> AeadCore for AesGcm<Aes, NonceSize>
where
Aes: NewBlockCipher + BlockCipher<BlockSize = U16> + BlockEncrypt,
Aes::ParBlocks: ArrayLength<Block<Aes>>,
NonceSize: ArrayLength<u8>,
{
type NonceSize = NonceSize;
Expand All @@ -236,36 +225,30 @@ where

impl<Aes, NonceSize> AeadInPlace for AesGcm<Aes, NonceSize>
where
Aes: NewBlockCipher + BlockCipher<BlockSize = U16> + BlockEncrypt,
Aes::ParBlocks: ArrayLength<Block<Aes>>,
Aes: BlockCipher + BlockSizeUser<BlockSize = U16> + BlockEncrypt,
NonceSize: ArrayLength<u8>,
{
fn encrypt_in_place_detached(
&self,
nonce: &Nonce<Self::NonceSize>,
nonce: &GenericArray<u8, NonceSize>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Tag, Error> {
if buffer.len() as u64 > P_MAX || associated_data.len() as u64 > A_MAX {
return Err(Error);
}

let (ctr, mask) = self.init_ctr(nonce);

// TODO(tarcieri): interleave encryption with GHASH
// See: <https://github.com/RustCrypto/AEADs/issues/74>
let mut ctr = self.init_ctr(nonce);
ctr.seek(Aes::BlockSize::to_usize());
ctr.apply_keystream(buffer);

let mut tag = self.compute_tag(associated_data, buffer);
ctr.seek(0);
ctr.apply_keystream(tag.as_mut_slice());

Ok(tag)
ctr.apply_keystream_partial(buffer.into());
Ok(self.compute_tag(mask, associated_data, buffer))
}

fn decrypt_in_place_detached(
&self,
nonce: &Nonce<Self::NonceSize>,
nonce: &GenericArray<u8, Self::NonceSize>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &Tag,
Expand All @@ -274,15 +257,15 @@ where
return Err(Error);
}

let (ctr, mask) = self.init_ctr(nonce);

// TODO(tarcieri): interleave encryption with GHASH
// See: <https://github.com/RustCrypto/AEADs/issues/74>
let mut expected_tag = self.compute_tag(associated_data, buffer);
let mut ctr = self.init_ctr(nonce);
ctr.apply_keystream(expected_tag.as_mut_slice());
let expected_tag = self.compute_tag(mask, associated_data, buffer);
ctr.apply_keystream_partial(buffer.into());

use subtle::ConstantTimeEq;
if expected_tag.ct_eq(tag).unwrap_u8() == 1 {
ctr.apply_keystream(buffer);
Ok(())
} else {
Err(Error)
Expand All @@ -292,8 +275,7 @@ where

impl<Aes, NonceSize> AesGcm<Aes, NonceSize>
where
Aes: NewBlockCipher + BlockCipher<BlockSize = U16> + BlockEncrypt,
Aes::ParBlocks: ArrayLength<Block<Aes>>,
Aes: BlockCipher + BlockSizeUser<BlockSize = U16> + BlockEncrypt,
NonceSize: ArrayLength<u8>,
{
/// Initialize counter mode.
Expand All @@ -305,7 +287,7 @@ where
/// > If len(IV)=96, then J0 = IV || 0{31} || 1.
/// > If len(IV) ≠ 96, then let s = 128 ⎡len(IV)/128⎤-len(IV), and
/// > J0=GHASH(IV||0s+64||[len(IV)]64).
fn init_ctr(&self, nonce: &Nonce<NonceSize>) -> Ctr32BE<&Aes> {
fn init_ctr(&self, nonce: &GenericArray<u8, NonceSize>) -> (Ctr32BE<&Aes>, Block) {
let j0 = if NonceSize::to_usize() == 12 {
let mut block = ghash::Block::default();
block[..12].copy_from_slice(nonce);
Expand All @@ -322,11 +304,14 @@ where
ghash.finalize().into_bytes()
};

Ctr32BE::from_block_cipher(&self.cipher, &j0)
let mut ctr = Ctr32BE::inner_iv_init(&self.cipher, &j0);
let mut tag_mask = Block::default();
ctr.write_keystream_block(&mut tag_mask);
(ctr, tag_mask)
}

/// Authenticate the given plaintext and associated data using GHASH
fn compute_tag(&self, associated_data: &[u8], buffer: &[u8]) -> Tag {
fn compute_tag(&self, mask: Block, associated_data: &[u8], buffer: &[u8]) -> Tag {
let mut ghash = self.ghash.clone();
ghash.update_padded(associated_data);
ghash.update_padded(buffer);
Expand All @@ -338,6 +323,12 @@ where
block[..8].copy_from_slice(&associated_data_bits.to_be_bytes());
block[8..].copy_from_slice(&buffer_bits.to_be_bytes());
ghash.update(&block);
ghash.finalize().into_bytes()

let mut tag = ghash.finalize().into_bytes();
for (a, b) in tag.as_mut_slice().iter_mut().zip(mask.as_slice()) {
*a ^= *b;
}

tag
}
}
4 changes: 1 addition & 3 deletions aes-gcm/tests/aes128gcm.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
//! AES-128-GCM tests
#[macro_use]
extern crate hex_literal;

#[macro_use]
mod common;

use self::common::TestVector;
use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead, Payload};
use aes_gcm::Aes128Gcm;
use hex_literal::hex;

/// NIST CAVS vectors
///
Expand Down
4 changes: 1 addition & 3 deletions aes-gcm/tests/aes256gcm.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
//! AES-256-GCM tests
#[macro_use]
extern crate hex_literal;

#[macro_use]
mod common;

use self::common::TestVector;
use aes_gcm::aead::{generic_array::GenericArray, Aead, NewAead, Payload};
use aes_gcm::Aes256Gcm;
use hex_literal::hex;

/// NIST CAVS vectors
///
Expand Down
Loading

0 comments on commit 5d05d05

Please sign in to comment.