Skip to content
Merged
Show file tree
Hide file tree
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
19 changes: 19 additions & 0 deletions .github/workflows/aes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,25 @@ jobs:
- run: cargo test --target ${{ matrix.target }}
- run: cargo test --target ${{ matrix.target }} --all-features

# Test for the portable software backend with a 16-bit word size
soft-16-bit:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- rust: 1.89.0 # MSRV
- rust: stable
env:
RUSTFLAGS: '-Dwarnings --cfg aes_backend="soft" --cfg cpubits="16"'
steps:
- uses: actions/checkout@v7
- uses: RustCrypto/actions/cargo-cache@master
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- run: cargo test
- run: cargo test --all-features

# Cross-compiled tests
cross:
strategy:
Expand Down
7 changes: 7 additions & 0 deletions aes/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.9.4 (UNRELEASED)
### Changed
- Reduce size of `Aes128/192/256` structs by using compact round key representation
for software backend ([#594])

[#594]: https://github.com/RustCrypto/block-ciphers/pull/594

## 0.9.3 (2026-08-28)
### Changed
- MSRV bumped to 1.89 ([#580])
Expand Down
36 changes: 18 additions & 18 deletions aes/src/backends/fixslice/aes192.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ pub(crate) fn key_schedule<W: Word>(key: &[u8; 24]) -> RoundKeys<W> {

loop {
for i in 0..8 {
rkeys[rk_off + i] = (W::uniform_row(0x0f) & (tmp[i] >> W::HALF_ROW))
| (W::uniform_row(0xf0) & (rkeys[(rk_off - 8) + i] << W::HALF_ROW));
rkeys[rk_off + i] = (W::uniform_row(0x3) & (tmp[i] >> W::HALF_ROW))
| (W::uniform_row(0xc) & (rkeys[(rk_off - 8) + i] << W::HALF_ROW));
}

sub_bytes(&mut tmp);
Expand All @@ -28,22 +28,22 @@ pub(crate) fn key_schedule<W: Word>(key: &[u8; 24]) -> RoundKeys<W> {

for i in 0..8 {
let mut ti = rkeys[rk_off + i];
ti ^= W::uniform_row(0x30) & tmp[i].ror(W::ror_distance(1, 1));
ti ^= W::uniform_row(0xc0) & (ti << W::QUARTER_ROW);
ti ^= W::uniform_row(0x4) & tmp[i].ror(W::ror_distance(1, 1));
ti ^= W::uniform_row(0x8) & (ti << W::QUARTER_ROW);
tmp[i] = ti;
}
rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp);
rk_off += 8;

for i in 0..8 {
let ui = tmp[i];
let mut ti = (W::uniform_row(0x0f) & (rkeys[(rk_off - 16) + i] >> W::HALF_ROW))
| (W::uniform_row(0xf0) & (ui << W::HALF_ROW));
ti ^= W::uniform_row(0x03) & (ui >> (3 * W::QUARTER_ROW));
let mut ti = (W::uniform_row(0x3) & (rkeys[(rk_off - 16) + i] >> W::HALF_ROW))
| (W::uniform_row(0xc) & (ui << W::HALF_ROW));
ti ^= W::uniform_row(0x1) & (ui >> (3 * W::QUARTER_ROW));
tmp[i] = ti
^ (W::uniform_row(0xfc) & (ti << W::QUARTER_ROW))
^ (W::uniform_row(0xf0) & (ti << W::HALF_ROW))
^ (W::uniform_row(0xc0) & (ti << (3 * W::QUARTER_ROW)));
^ (W::uniform_row(0xe) & (ti << W::QUARTER_ROW))
^ (W::uniform_row(0xc) & (ti << W::HALF_ROW))
^ (W::uniform_row(0x8) & (ti << (3 * W::QUARTER_ROW)));
}
rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp);
rk_off += 8;
Expand All @@ -55,13 +55,13 @@ pub(crate) fn key_schedule<W: Word>(key: &[u8; 24]) -> RoundKeys<W> {
rcon += 1;

for i in 0..8 {
let mut ti = (W::uniform_row(0x0f) & (rkeys[(rk_off - 16) + i] >> W::HALF_ROW))
| (W::uniform_row(0xf0) & (rkeys[(rk_off - 8) + i] << W::HALF_ROW));
ti ^= W::uniform_row(0x03) & tmp[i].ror(W::ror_distance(1, 3));
let mut ti = (W::uniform_row(0x3) & (rkeys[(rk_off - 16) + i] >> W::HALF_ROW))
| (W::uniform_row(0xc) & (rkeys[(rk_off - 8) + i] << W::HALF_ROW));
ti ^= W::uniform_row(0x1) & tmp[i].ror(W::ror_distance(1, 3));
rkeys[rk_off + i] = ti
^ (W::uniform_row(0xfc) & (ti << W::QUARTER_ROW))
^ (W::uniform_row(0xf0) & (ti << W::HALF_ROW))
^ (W::uniform_row(0xc0) & (ti << (3 * W::QUARTER_ROW)));
^ (W::uniform_row(0xe) & (ti << W::QUARTER_ROW))
^ (W::uniform_row(0xc) & (ti << W::HALF_ROW))
^ (W::uniform_row(0x8) & (ti << (3 * W::QUARTER_ROW)));
}
rk_off += 8;

Expand All @@ -72,8 +72,8 @@ pub(crate) fn key_schedule<W: Word>(key: &[u8; 24]) -> RoundKeys<W> {
for i in 0..8 {
let ui = rkeys[(rk_off - 8) + i];
let mut ti = rkeys[(rk_off - 16) + i];
ti ^= W::uniform_row(0x30) & (ui >> W::QUARTER_ROW);
ti ^= W::uniform_row(0xc0) & (ti << W::QUARTER_ROW);
ti ^= W::uniform_row(0x4) & (ui >> W::QUARTER_ROW);
ti ^= W::uniform_row(0x8) & (ti << W::QUARTER_ROW);
tmp[i] = ti;
}
}
Expand Down
16 changes: 8 additions & 8 deletions aes/src/backends/fixslice/mix_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,30 +145,30 @@ fn rotate_rows_2<W: Word>(x: W) -> W {

#[inline(always)]
fn rotate_rows_and_columns_1_1<W: Word>(x: W) -> W {
let a = x.ror(W::ror_distance(1, 1)) & W::uniform_row(0x3f);
let b = x.ror(W::ror_distance(0, 1)) & W::uniform_row(0xc0);
let a = x.ror(W::ror_distance(1, 1)) & W::uniform_row(0x7);
let b = x.ror(W::ror_distance(0, 1)) & W::uniform_row(0x8);
a | b
}

#[cfg(not(aes_backend_soft = "compact"))]
#[inline(always)]
fn rotate_rows_and_columns_1_2<W: Word>(x: W) -> W {
let a = x.ror(W::ror_distance(1, 2)) & W::uniform_row(0x0f);
let b = x.ror(W::ror_distance(0, 2)) & W::uniform_row(0xf0);
let a = x.ror(W::ror_distance(1, 2)) & W::uniform_row(0x3);
let b = x.ror(W::ror_distance(0, 2)) & W::uniform_row(0xc);
a | b
}

#[cfg(not(aes_backend_soft = "compact"))]
#[inline(always)]
fn rotate_rows_and_columns_1_3<W: Word>(x: W) -> W {
let a = x.ror(W::ror_distance(1, 3)) & W::uniform_row(0x03);
let b = x.ror(W::ror_distance(0, 3)) & W::uniform_row(0xfc);
let a = x.ror(W::ror_distance(1, 3)) & W::uniform_row(0x1);
let b = x.ror(W::ror_distance(0, 3)) & W::uniform_row(0xe);
a | b
}

#[inline(always)]
fn rotate_rows_and_columns_2_2<W: Word>(x: W) -> W {
let a = x.ror(W::ror_distance(2, 2)) & W::uniform_row(0x0f);
let b = x.ror(W::ror_distance(1, 2)) & W::uniform_row(0xf0);
let a = x.ror(W::ror_distance(2, 2)) & W::uniform_row(0x3);
let b = x.ror(W::ror_distance(1, 2)) & W::uniform_row(0xc);
a | b
}
8 changes: 6 additions & 2 deletions aes/src/backends/fixslice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ mod sbox;
mod utils;
mod word;

use word::Word;
pub(super) use word::Word;

type State<W> = [W; 8];

cpubits::cpubits! {
16 | 32 => {
16 => {
pub(super) type NativeWord = u16;
}
Comment thread
newpavlov marked this conversation as resolved.
32 => {
pub(super) type NativeWord = u32;
}
64 => {
Expand All @@ -41,3 +44,4 @@ cpubits::cpubits! {

pub(super) type NativeBatchSize = <NativeWord as Word>::Blocks;
pub(super) type BatchBlocks<W> = Array<crate::Block, <W as Word>::Blocks>;
pub(super) type MinWord = u16;
20 changes: 10 additions & 10 deletions aes/src/backends/fixslice/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pub(super) fn delta_swap_2<W: Word>(a: &mut W, b: &mut W, shift: u32, mask: W) {
pub(super) fn shift_rows_1<W: Word>(state: &mut [W]) {
debug_assert_eq!(state.len(), 8);
for x in state.iter_mut() {
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x00, 0x03, 0x0f, 0x0c));
delta_swap_1(x, W::QUARTER_ROW, W::pack_rows(0x00, 0x33, 0x00, 0x33));
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x0, 0x1, 0x3, 0x2));
delta_swap_1(x, W::QUARTER_ROW, W::pack_rows(0x0, 0x5, 0x0, 0x5));
}
}

Expand All @@ -42,7 +42,7 @@ pub(super) fn shift_rows_1<W: Word>(state: &mut [W]) {
pub(super) fn shift_rows_2<W: Word>(state: &mut [W]) {
debug_assert_eq!(state.len(), 8);
for x in state.iter_mut() {
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x00, 0x0f, 0x00, 0x0f));
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x0, 0x3, 0x0, 0x3));
}
}

Expand All @@ -51,8 +51,8 @@ pub(super) fn shift_rows_2<W: Word>(state: &mut [W]) {
pub(super) fn shift_rows_3<W: Word>(state: &mut [W]) {
debug_assert_eq!(state.len(), 8);
for x in state.iter_mut() {
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x00, 0x0c, 0x0f, 0x03));
delta_swap_1(x, W::QUARTER_ROW, W::pack_rows(0x00, 0x33, 0x00, 0x33));
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x0, 0x2, 0x3, 0x1));
delta_swap_1(x, W::QUARTER_ROW, W::pack_rows(0x0, 0x5, 0x0, 0x5));
}
}

Expand Down Expand Up @@ -83,11 +83,11 @@ pub(super) fn inv_shift_rows_3<W: Word>(state: &mut [W]) {
pub(super) fn xor_columns<W: Word>(rkeys: &mut [W], offset: usize, idx_xor: usize, idx_ror: u32) {
for i in 0..8 {
let off_i = offset + i;
let rk = rkeys[off_i - idx_xor] ^ (W::uniform_row(0x03) & rkeys[off_i].ror(idx_ror));
let rk = rkeys[off_i - idx_xor] ^ (W::uniform_row(0x1) & rkeys[off_i].ror(idx_ror));
rkeys[off_i] = rk
^ (W::uniform_row(0xfc) & (rk << W::QUARTER_ROW))
^ (W::uniform_row(0xf0) & (rk << W::HALF_ROW))
^ (W::uniform_row(0xc0) & (rk << (3 * W::QUARTER_ROW)));
^ (W::uniform_row(0xe) & (rk << W::QUARTER_ROW))
^ (W::uniform_row(0xc) & (rk << W::HALF_ROW))
^ (W::uniform_row(0x8) & (rk << (3 * W::QUARTER_ROW)));
}
}

Expand Down Expand Up @@ -115,5 +115,5 @@ pub(super) fn add_round_key<W: Word>(state: &mut State<W>, rkey: &[W]) {

#[inline(always)]
pub(super) fn add_round_constant_bit<W: Word>(state: &mut [W], bit: usize) {
state[bit] ^= W::pack_rows(0x00, 0xc0, 0x00, 0x00);
state[bit] ^= W::pack_rows(0x0, 0x8, 0x0, 0x0);
}
Loading