Skip to content

Commit

Permalink
aes: Clarify counter overflow checking.
Browse files Browse the repository at this point in the history
Move `Conuter` and `Iv` to aes/counter.rs.

Create a more robust internal API for counter/nonce/IV management that
makes the usage within AES-GCM more clearly correct. The new design is
easier to test.

`git difftool HEAD^1:src/aead/aes.rs src/aead/aes/counter.rs`
  • Loading branch information
briansmith committed Jun 28, 2024
1 parent 9d214d6 commit 1352dcb
Show file tree
Hide file tree
Showing 10 changed files with 585 additions and 110 deletions.
30 changes: 23 additions & 7 deletions src/aead/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ use crate::{
use cfg_if::cfg_if;
use core::ops::RangeFrom;

pub(super) use self::{counter::Iv, ffi::Counter};
pub(super) use self::{
counter::{CounterOverflowError, Iv, IvBlock},
ffi::Counter,
};

#[macro_use]
mod ffi;
Expand Down Expand Up @@ -114,6 +117,14 @@ pub enum KeyBytes<'a> {
AES_256(&'a [u8; AES_256_KEY_LEN]),
}

pub(super) struct InOutLenInconsistentWithIvBlockLenError(());
impl InOutLenInconsistentWithIvBlockLenError {
#[cold]
fn new() -> Self {
Self(())
}
}

pub(super) type Block = [u8; BLOCK_LEN];
pub(super) const BLOCK_LEN: usize = 16;
pub(super) const ZERO_BLOCK: Block = [0u8; BLOCK_LEN];
Expand All @@ -124,7 +135,12 @@ pub(super) trait EncryptBlock {
}

pub(super) trait EncryptCtr32 {
fn ctr32_encrypt_within(&self, in_out: &mut [u8], src: RangeFrom<usize>, ctr: &mut Counter);
fn ctr32_encrypt_within(
&self,
in_out: &mut [u8],
src: RangeFrom<usize>,
iv_block: IvBlock,
) -> Result<(), InOutLenInconsistentWithIvBlockLenError>;
}

#[allow(dead_code)]
Expand All @@ -144,11 +160,11 @@ fn encrypt_iv_xor_block_using_encrypt_block(

#[allow(dead_code)]
fn encrypt_iv_xor_block_using_ctr32(key: &impl EncryptCtr32, iv: Iv, mut block: Block) -> Block {
// This is OK because we're only encrypting one block, and `iv` is already
// reserved for us to use.
let mut ctr = Counter(iv.into_block_less_safe());
key.ctr32_encrypt_within(&mut block, 0.., &mut ctr);
block
let iv_block = IvBlock::from_iv(iv);
match key.ctr32_encrypt_within(&mut block, 0.., iv_block) {
Ok(()) => block,
Result::<_, InOutLenInconsistentWithIvBlockLenError>::Err(_) => unreachable!(),
}
}

#[cfg(test)]
Expand Down
14 changes: 10 additions & 4 deletions src/aead/aes/bs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#![cfg(target_arch = "arm")]

use super::{Counter, AES_KEY};
use super::{IvBlock, AES_KEY};
use core::ops::RangeFrom;

/// SAFETY:
Expand All @@ -31,8 +31,8 @@ pub(super) unsafe fn ctr32_encrypt_blocks_with_vpaes_key(
in_out: &mut [u8],
src: RangeFrom<usize>,
vpaes_key: &AES_KEY,
ctr: &mut Counter,
) {
iv_block: IvBlock,
) -> Result<(), super::InOutLenInconsistentWithIvBlockLenError> {
prefixed_extern! {
// bsaes_ctr32_encrypt_blocks requires transformation of an existing
// VPAES key; there is no `bsaes_set_encrypt_key`.
Expand All @@ -57,6 +57,12 @@ pub(super) unsafe fn ctr32_encrypt_blocks_with_vpaes_key(
// * `bsaes_ctr32_encrypt_blocks` satisfies the contract for
// `ctr32_encrypt_blocks`.
unsafe {
ctr32_encrypt_blocks!(bsaes_ctr32_encrypt_blocks, in_out, src, &bsaes_key, ctr);
ctr32_encrypt_blocks!(
bsaes_ctr32_encrypt_blocks,
in_out,
src,
&bsaes_key,
iv_block
)
}
}
Loading

0 comments on commit 1352dcb

Please sign in to comment.