Skip to content

Commit

Permalink
serpent: add serpent_no_unroll configuration flag (#476)
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov authored Feb 28, 2025
1 parent 70fe50a commit cbdb9f0
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 71 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/serpent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
toolchain: ${{ matrix.rust }}
targets: ${{ matrix.target }}
- run: cargo build --no-default-features --release --target ${{ matrix.target }}
- env:
RUSTFLAGS: "-Dwarnings --cfg serpent_no_unroll"
run: cargo build --no-default-features --release --target ${{ matrix.target }}

minimal-versions:
if: false # TODO: temp disabled due to unpublished prerelease dependencies
Expand All @@ -60,3 +63,6 @@ jobs:
- run: cargo test --no-default-features
- run: cargo test
- run: cargo test --all-features
- env:
RUSTFLAGS: "-Dwarnings --cfg serpent_no_unroll"
run: cargo test --all-features
10 changes: 10 additions & 0 deletions serpent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ 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.6.0 (UNRELEASED)
### Added
- `serpent_no_unroll` configuration flag ([#476])

### Changed
- Improve bitslicing implementation ([#474])

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

## 0.5.1 (2022-02-17)
### Fixed
- Minimal versions build ([#303])
Expand Down
3 changes: 3 additions & 0 deletions serpent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ zeroize = ["cipher/zeroize"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(serpent_no_unroll)'] }
8 changes: 8 additions & 0 deletions serpent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ architectures.

USE AT YOUR OWN RISK!

## Configuration flags

You can modify crate using the following configuration flags:

- `serpent_no_unroll`: do not unroll rounds loop. Reduces binary size at the cost of slightly lower performance.

The flag can be enabled using RUSTFLAGS environmental variable (e.g. RUSTFLAGS="--cfg serpent_no_unroll") or by modifying .cargo/config.

## Minimum Supported Rust Version

Rust **1.65** or higher.
Expand Down
2 changes: 0 additions & 2 deletions serpent/src/bitslice.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//!
//! Serpent uses 8 4-bit Sboxes which were designed to be implemented using small
//! circuits. For each block these Sboxes are applied in a bitsliced fashion.
//!
Expand All @@ -11,7 +10,6 @@
//!
//! "Speeding Up Serpent", Osvik
//! <https://www.ii.uib.no/~osvik/pub/aes3.pdf>
//!
use crate::Words;

Expand Down
73 changes: 4 additions & 69 deletions serpent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ use cipher::{
use core::fmt;

mod bitslice;
#[macro_use]
mod unroll;

#[cfg(feature = "zeroize")]
use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
Expand All @@ -56,73 +58,6 @@ fn xor(b1: Words, k: Words) -> Words {
res
}

macro_rules! repeat31 {
($i:ident, $body:block) => {
let $i = 0;
$body;
let $i = 1;
$body;
let $i = 2;
$body;
let $i = 3;
$body;
let $i = 4;
$body;
let $i = 5;
$body;
let $i = 6;
$body;
let $i = 7;
$body;
let $i = 8;
$body;
let $i = 9;
$body;
let $i = 10;
$body;
let $i = 11;
$body;
let $i = 12;
$body;
let $i = 13;
$body;
let $i = 14;
$body;
let $i = 15;
$body;
let $i = 16;
$body;
let $i = 17;
$body;
let $i = 18;
$body;
let $i = 19;
$body;
let $i = 20;
$body;
let $i = 21;
$body;
let $i = 22;
$body;
let $i = 23;
$body;
let $i = 24;
$body;
let $i = 25;
$body;
let $i = 26;
$body;
let $i = 27;
$body;
let $i = 28;
$body;
let $i = 29;
$body;
let $i = 30;
$body;
};
}

fn expand_key(source: &[u8], len_bits: usize) -> [u8; 32] {
let mut key = [0u8; 32];
key[..source.len()].copy_from_slice(source);
Expand Down Expand Up @@ -208,7 +143,7 @@ impl BlockCipherEncBackend for Serpent {
fn encrypt_block(&self, mut block: InOut<'_, '_, Block<Self>>) {
let mut b: [u32; 4] = read_words(block.get_in().into());

repeat31!(i, {
unroll31!(i, {
let xb = xor(b, self.round_keys[i]);
let s = bitslice::apply_s(i, xb);
b = bitslice::linear_transform(s);
Expand Down Expand Up @@ -238,7 +173,7 @@ impl BlockCipherDecBackend for Serpent {
let xb = bitslice::apply_s_inv(ROUNDS - 1, s);
b = xor(xb, self.round_keys[ROUNDS - 1]);

repeat31!(i, {
unroll31!(i, {
let i = 30 - i;
let s = bitslice::linear_transform_inv(b);
let xb = bitslice::apply_s_inv(i, s);
Expand Down
46 changes: 46 additions & 0 deletions serpent/src/unroll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#[cfg(not(serpent_no_unroll))]
#[rustfmt::skip]
macro_rules! unroll31 {
($i:ident, $body:block) => {
let $i = 0; $body;
let $i = 1; $body;
let $i = 2; $body;
let $i = 3; $body;
let $i = 4; $body;
let $i = 5; $body;
let $i = 6; $body;
let $i = 7; $body;
let $i = 8; $body;
let $i = 9; $body;
let $i = 10; $body;
let $i = 11; $body;
let $i = 12; $body;
let $i = 13; $body;
let $i = 14; $body;
let $i = 15; $body;
let $i = 16; $body;
let $i = 17; $body;
let $i = 18; $body;
let $i = 19; $body;
let $i = 20; $body;
let $i = 21; $body;
let $i = 22; $body;
let $i = 23; $body;
let $i = 24; $body;
let $i = 25; $body;
let $i = 26; $body;
let $i = 27; $body;
let $i = 28; $body;
let $i = 29; $body;
let $i = 30; $body;
};
}

#[cfg(serpent_no_unroll)]
macro_rules! unroll31 {
($i:ident, $body:block) => {
for $i in 0..31 {
$body;
}
};
}

0 comments on commit cbdb9f0

Please sign in to comment.