Skip to content

Commit adfead3

Browse files
authored
chacha20: bring back rand_core support (#333)
Allows the crate's AVX2 / NEON implementations to be used as `rand_core`-compatible RNGs. See also: rust-random/rand#934
1 parent fea3dd0 commit adfead3

20 files changed

+2038
-486
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
target/
2-
**/Cargo.lock
2+
**/Cargo.lock

Cargo.lock

+135-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benches/Cargo.toml

+7-5
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ publish = false
99

1010
[workspace]
1111

12-
[dev-dependencies]
13-
criterion = "0.3"
14-
criterion-cycles-per-byte = "0.1"
15-
chacha20 = { path = "../chacha20/" }
12+
[dependencies]
13+
criterion = "0.5"
14+
chacha20 = { path = "../chacha20/", features = ["rng", "zeroize"] }
15+
16+
[target.'cfg(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux")))'.dependencies]
17+
criterion-cycles-per-byte = "0.6.0"
1618

1719
[[bench]]
1820
name = "chacha20"
1921
path = "src/chacha20.rs"
20-
harness = false
22+
harness = false

benches/README.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Benching ChaCha20
2+
3+
## A note from the criterion-cycles-per-byte github
4+
```
5+
[`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.
6+
```
7+
8+
## ChaCha20 Cipher benching
9+
You can bench the ChaCha20 cipher using `cargo bench -- apply_keystream`
10+
11+
## ChaCha20Rng benching
12+
You can bench ChaCha20Rng using `cargo bench -- fill_bytes`
13+
14+
## Measuring CPB for aarch64
15+
`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):
16+
```
17+
Running src/chacha20.rs (target/release/deps/chacha20-02f555ae0af3670b)
18+
Gnuplot not found, using plotters backend
19+
Benchmarking stream-cipher/apply_keystream/1024: Warming up for 3.0000 serror: bench failed, to rerun pass `--bench chacha20`
20+
21+
Caused by:
22+
process didn't exit successfully: `..../benches/target/release/deps/chacha20-02f555ae0af3670b --bench` (signal: 4, SIGILL: illegal instruction)
23+
```
24+
25+
The following adjustment can fix this.
26+
27+
### Installing the cycle counter Linux Kernel Module on a Raspberry Pi 4b
28+
```
29+
$ sudo apt-get update
30+
$ sudo apt-get upgrade
31+
$ sudo apt-get install build-essential raspberrypi-kernel-headers
32+
# cd to your chosen directory
33+
$ cd ../..
34+
$ git clone https://github.com/jerinjacobk/armv8_pmu_cycle_counter_el0.git
35+
$ cd armv8_pmu_cycle_counter_el10
36+
$ make
37+
$ sudo insmod pmu_el0_cycle_counter.ko
38+
# Verifying that it is installed
39+
$ lsmod | grep pmu_el0_cycle_counter
40+
pmu_el0_cycle_counter 16384 0
41+
```
42+
Without any other commands, this module will be deactivated after every reboot, and can be reactivated using
43+
```
44+
$ cd armv8_pmu_cycle_counter_el10
45+
$ sudo insmod pmu_el0_cycle_counter.ko
46+
```

benches/src/chacha20.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
//! ChaCha20 benchmark
22
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
3-
use criterion_cycles_per_byte::CyclesPerByte;
3+
use benches::{criterion_group_bench, Benchmarker};
44

55
use chacha20::{
66
cipher::{KeyIvInit, StreamCipher},
77
ChaCha20,
88
};
99

1010
const KB: usize = 1024;
11-
12-
fn bench(c: &mut Criterion<CyclesPerByte>) {
11+
fn bench(c: &mut Benchmarker) {
1312
let mut group = c.benchmark_group("stream-cipher");
1413

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

31-
criterion_group!(
32-
name = benches;
33-
config = Criterion::default().with_measurement(CyclesPerByte);
34-
targets = bench
30+
use chacha20::rand_core::{RngCore, SeedableRng};
31+
32+
fn bench_chacha20rng(c: &mut Benchmarker) {
33+
let mut group = c.benchmark_group("ChaCha20Rng");
34+
35+
for size in &[KB, 2 * KB, 4 * KB, 8 * KB, 16 * KB] {
36+
let mut buf = vec![0u8; *size];
37+
38+
group.throughput(Throughput::Bytes(*size as u64));
39+
40+
group.bench_function(BenchmarkId::new("fill_bytes", size), |b| {
41+
let mut rng = chacha20::ChaCha20Rng::from_seed([0u8; 32]);
42+
b.iter(|| rng.fill_bytes(&mut buf));
43+
});
44+
}
45+
46+
group.finish();
47+
}
48+
criterion_group_bench!(
49+
benches_chacha20rng,
50+
bench_chacha20rng
3551
);
36-
criterion_main!(benches);
52+
53+
criterion_group_bench!(
54+
benches,
55+
bench
56+
);
57+
58+
criterion_main!(benches, benches_chacha20rng);

benches/src/lib.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
1+
use criterion::Criterion;
12

3+
#[cfg(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux")))]
4+
pub type Benchmarker = Criterion<criterion_cycles_per_byte::CyclesPerByte>;
5+
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux"))))]
6+
pub type Benchmarker = Criterion;
7+
8+
#[macro_export]
9+
macro_rules! criterion_group_bench {
10+
($Name:ident, $Target:ident) => {
11+
#[cfg(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux")))]
12+
criterion_group!(
13+
name = $Name;
14+
config = Criterion::default().with_measurement(criterion_cycles_per_byte::CyclesPerByte);
15+
targets = $Target
16+
);
17+
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86", all(target_arch = "aarch64", target_os = "linux"))))]
18+
criterion_group!(
19+
name = $Name;
20+
config = Criterion::default();
21+
targets = $Target
22+
);
23+
}
24+
}

0 commit comments

Comments
 (0)