Skip to content

Commit

Permalink
chacha20: bring back rand_core support (#333)
Browse files Browse the repository at this point in the history
Allows the crate's AVX2 / NEON implementations to be used as
`rand_core`-compatible RNGs.

See also: rust-random/rand#934
  • Loading branch information
nstilt1 authored Apr 29, 2024
1 parent fea3dd0 commit adfead3
Show file tree
Hide file tree
Showing 20 changed files with 2,038 additions and 486 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
target/
**/Cargo.lock
**/Cargo.lock
143 changes: 135 additions & 8 deletions Cargo.lock

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

12 changes: 7 additions & 5 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ publish = false

[workspace]

[dev-dependencies]
criterion = "0.3"
criterion-cycles-per-byte = "0.1"
chacha20 = { path = "../chacha20/" }
[dependencies]
criterion = "0.5"
chacha20 = { path = "../chacha20/", features = ["rng", "zeroize"] }

[target.'cfg(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux")))'.dependencies]
criterion-cycles-per-byte = "0.6.0"

[[bench]]
name = "chacha20"
path = "src/chacha20.rs"
harness = false
harness = false
46 changes: 46 additions & 0 deletions benches/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Benching ChaCha20

## A note from the criterion-cycles-per-byte github
```
[`criterion-cycles-per-byte`] measures clock ticks rather than cycles. It will not provide accurate results on modern machines unless you calculate the ratio of ticks to cycles and take steps to ensure that that ratio remains consistent.
```

## ChaCha20 Cipher benching
You can bench the ChaCha20 cipher using `cargo bench -- apply_keystream`

## ChaCha20Rng benching
You can bench ChaCha20Rng using `cargo bench -- fill_bytes`

## Measuring CPB for aarch64
`criterion-cycles-per-byte` can work on `aarch64` with Linux, but it might produce an error. This error occurred on an up-to-date Raspberry Pi 4b (as of 12/14/2023):
```
Running src/chacha20.rs (target/release/deps/chacha20-02f555ae0af3670b)
Gnuplot not found, using plotters backend
Benchmarking stream-cipher/apply_keystream/1024: Warming up for 3.0000 serror: bench failed, to rerun pass `--bench chacha20`
Caused by:
process didn't exit successfully: `..../benches/target/release/deps/chacha20-02f555ae0af3670b --bench` (signal: 4, SIGILL: illegal instruction)
```

The following adjustment can fix this.

### Installing the cycle counter Linux Kernel Module on a Raspberry Pi 4b
```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install build-essential raspberrypi-kernel-headers
# cd to your chosen directory
$ cd ../..
$ git clone https://github.com/jerinjacobk/armv8_pmu_cycle_counter_el0.git
$ cd armv8_pmu_cycle_counter_el10
$ make
$ sudo insmod pmu_el0_cycle_counter.ko
# Verifying that it is installed
$ lsmod | grep pmu_el0_cycle_counter
pmu_el0_cycle_counter 16384 0
```
Without any other commands, this module will be deactivated after every reboot, and can be reactivated using
```
$ cd armv8_pmu_cycle_counter_el10
$ sudo insmod pmu_el0_cycle_counter.ko
```
38 changes: 30 additions & 8 deletions benches/src/chacha20.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
//! ChaCha20 benchmark
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use criterion_cycles_per_byte::CyclesPerByte;
use benches::{criterion_group_bench, Benchmarker};

use chacha20::{
cipher::{KeyIvInit, StreamCipher},
ChaCha20,
};

const KB: usize = 1024;

fn bench(c: &mut Criterion<CyclesPerByte>) {
fn bench(c: &mut Benchmarker) {
let mut group = c.benchmark_group("stream-cipher");

for size in &[KB, 2 * KB, 4 * KB, 8 * KB, 16 * KB] {
Expand All @@ -28,9 +27,32 @@ fn bench(c: &mut Criterion<CyclesPerByte>) {
group.finish();
}

criterion_group!(
name = benches;
config = Criterion::default().with_measurement(CyclesPerByte);
targets = bench
use chacha20::rand_core::{RngCore, SeedableRng};

fn bench_chacha20rng(c: &mut Benchmarker) {
let mut group = c.benchmark_group("ChaCha20Rng");

for size in &[KB, 2 * KB, 4 * KB, 8 * KB, 16 * KB] {
let mut buf = vec![0u8; *size];

group.throughput(Throughput::Bytes(*size as u64));

group.bench_function(BenchmarkId::new("fill_bytes", size), |b| {
let mut rng = chacha20::ChaCha20Rng::from_seed([0u8; 32]);
b.iter(|| rng.fill_bytes(&mut buf));
});
}

group.finish();
}
criterion_group_bench!(
benches_chacha20rng,
bench_chacha20rng
);
criterion_main!(benches);

criterion_group_bench!(
benches,
bench
);

criterion_main!(benches, benches_chacha20rng);
23 changes: 23 additions & 0 deletions benches/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
use criterion::Criterion;

#[cfg(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux")))]
pub type Benchmarker = Criterion<criterion_cycles_per_byte::CyclesPerByte>;
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux"))))]
pub type Benchmarker = Criterion;

#[macro_export]
macro_rules! criterion_group_bench {
($Name:ident, $Target:ident) => {
#[cfg(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux")))]
criterion_group!(
name = $Name;
config = Criterion::default().with_measurement(criterion_cycles_per_byte::CyclesPerByte);
targets = $Target
);
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux"))))]
criterion_group!(
name = $Name;
config = Criterion::default();
targets = $Target
);
}
}
Loading

0 comments on commit adfead3

Please sign in to comment.