From d3386b765ca61cf38e8807bfae319c662b35e663 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 9 Jun 2022 17:30:08 -0600 Subject: [PATCH] p256: criterion benchmarks (#597) Adapts the benchmarks added in the `p384` crate in #588 to the `p256` crate, with the goal of using them to measure the performance impact of switching to fiat-crypto's arithmetic implementations. --- Cargo.lock | 1 + p256/Cargo.toml | 11 +++++++ p256/benches/field.rs | 54 ++++++++++++++++++++++++++++++ p256/benches/scalar.rs | 75 ++++++++++++++++++++++++++++++++++++++++++ p256/src/arithmetic.rs | 2 +- p256/src/lib.rs | 3 ++ p384/Cargo.toml | 2 +- 7 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 p256/benches/field.rs create mode 100644 p256/benches/scalar.rs diff --git a/Cargo.lock b/Cargo.lock index 5f7551ad..690171bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -608,6 +608,7 @@ name = "p256" version = "0.11.0" dependencies = [ "blobby", + "criterion", "ecdsa", "elliptic-curve", "hex-literal", diff --git a/p256/Cargo.toml b/p256/Cargo.toml index b197ff48..e11e601b 100644 --- a/p256/Cargo.toml +++ b/p256/Cargo.toml @@ -27,6 +27,7 @@ sha2 = { version = "0.10", optional = true, default-features = false } [dev-dependencies] blobby = "0.3" +criterion = "0.3" ecdsa-core = { version = "0.14", package = "ecdsa", default-features = false, features = ["dev"] } hex-literal = "0.3" proptest = "1.0" @@ -39,6 +40,7 @@ bits = ["arithmetic", "elliptic-curve/bits"] digest = ["ecdsa-core/digest", "ecdsa-core/hazmat"] ecdh = ["arithmetic", "elliptic-curve/ecdh"] ecdsa = ["arithmetic", "ecdsa-core/sign", "ecdsa-core/verify", "sha256"] +expose-field = ["arithmetic"] hash2curve = ["arithmetic", "elliptic-curve/hash2curve"] jwk = ["elliptic-curve/jwk"] pem = ["elliptic-curve/pem", "ecdsa-core/pem", "pkcs8"] @@ -52,3 +54,12 @@ voprf = ["elliptic-curve/voprf", "sha2"] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] + +[[bench]] +name = "field" +harness = false +required-features = ["expose-field"] + +[[bench]] +name = "scalar" +harness = false diff --git a/p256/benches/field.rs b/p256/benches/field.rs new file mode 100644 index 00000000..43ece839 --- /dev/null +++ b/p256/benches/field.rs @@ -0,0 +1,54 @@ +//! secp256r1 field element benchmarks + +use criterion::{ + criterion_group, criterion_main, measurement::Measurement, BenchmarkGroup, Criterion, +}; +use hex_literal::hex; +use p256::FieldElement; + +fn test_field_element_x() -> FieldElement { + FieldElement::from_bytes( + &hex!("1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83").into(), + ) + .unwrap() +} + +fn test_field_element_y() -> FieldElement { + FieldElement::from_bytes( + &hex!("ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9").into(), + ) + .unwrap() +} + +fn bench_field_element_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_field_element_x(); + let y = test_field_element_y(); + group.bench_function("mul", |b| b.iter(|| &x * &y)); +} + +fn bench_field_element_square<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_field_element_x(); + group.bench_function("square", |b| b.iter(|| x.square())); +} + +fn bench_field_element_sqrt<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_field_element_x(); + group.bench_function("sqrt", |b| b.iter(|| x.sqrt())); +} + +fn bench_field_element_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_field_element_x(); + group.bench_function("invert", |b| b.iter(|| x.invert())); +} + +fn bench_field_element(c: &mut Criterion) { + let mut group = c.benchmark_group("field element operations"); + bench_field_element_mul(&mut group); + bench_field_element_square(&mut group); + bench_field_element_invert(&mut group); + bench_field_element_sqrt(&mut group); + group.finish(); +} + +criterion_group!(benches, bench_field_element); +criterion_main!(benches); diff --git a/p256/benches/scalar.rs b/p256/benches/scalar.rs new file mode 100644 index 00000000..a8db8d5d --- /dev/null +++ b/p256/benches/scalar.rs @@ -0,0 +1,75 @@ +//! secp256r1 scalar arithmetic benchmarks + +use criterion::{ + criterion_group, criterion_main, measurement::Measurement, BenchmarkGroup, Criterion, +}; +use hex_literal::hex; +use p256::{elliptic_curve::group::ff::PrimeField, ProjectivePoint, Scalar}; + +fn test_scalar_x() -> Scalar { + Scalar::from_repr( + hex!("519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464").into(), + ) + .unwrap() +} + +fn test_scalar_y() -> Scalar { + Scalar::from_repr( + hex!("0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813").into(), + ) + .unwrap() +} + +fn bench_point_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let p = ProjectivePoint::GENERATOR; + let m = test_scalar_x(); + let s = Scalar::from_repr(m.into()).unwrap(); + group.bench_function("point-scalar mul", |b| b.iter(|| &p * &s)); +} + +fn bench_scalar_sub<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_scalar_x(); + let y = test_scalar_y(); + group.bench_function("sub", |b| b.iter(|| &x - &y)); +} + +fn bench_scalar_add<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_scalar_x(); + let y = test_scalar_y(); + group.bench_function("add", |b| b.iter(|| &x + &y)); +} + +fn bench_scalar_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_scalar_x(); + let y = test_scalar_y(); + group.bench_function("mul", |b| b.iter(|| &x * &y)); +} + +fn bench_scalar_negate<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_scalar_x(); + group.bench_function("negate", |b| b.iter(|| -x)); +} + +fn bench_scalar_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { + let x = test_scalar_x(); + group.bench_function("invert", |b| b.iter(|| x.invert())); +} + +fn bench_point(c: &mut Criterion) { + let mut group = c.benchmark_group("point operations"); + bench_point_mul(&mut group); + group.finish(); +} + +fn bench_scalar(c: &mut Criterion) { + let mut group = c.benchmark_group("scalar operations"); + bench_scalar_sub(&mut group); + bench_scalar_add(&mut group); + bench_scalar_mul(&mut group); + bench_scalar_negate(&mut group); + bench_scalar_invert(&mut group); + group.finish(); +} + +criterion_group!(benches, bench_point, bench_scalar); +criterion_main!(benches); diff --git a/p256/src/arithmetic.rs b/p256/src/arithmetic.rs index 7cec8dd9..22b63c2a 100644 --- a/p256/src/arithmetic.rs +++ b/p256/src/arithmetic.rs @@ -1,7 +1,7 @@ //! Pure Rust implementation of group operations on secp256r1. pub(crate) mod affine; -mod field; +pub(crate) mod field; #[cfg(feature = "hash2curve")] mod hash2curve; pub(crate) mod projective; diff --git a/p256/src/lib.rs b/p256/src/lib.rs index 258fd727..bb323c4a 100644 --- a/p256/src/lib.rs +++ b/p256/src/lib.rs @@ -43,6 +43,9 @@ pub use arithmetic::{ scalar::{blinded::BlindedScalar, Scalar}, }; +#[cfg(feature = "expose-field")] +pub use arithmetic::field::FieldElement; + #[cfg(feature = "pkcs8")] #[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] pub use elliptic_curve::pkcs8; diff --git a/p384/Cargo.toml b/p384/Cargo.toml index a6471142..ba21e60b 100644 --- a/p384/Cargo.toml +++ b/p384/Cargo.toml @@ -40,7 +40,7 @@ bits = ["arithmetic", "elliptic-curve/bits"] digest = ["ecdsa-core/digest", "ecdsa-core/hazmat"] ecdh = ["arithmetic", "elliptic-curve/ecdh"] ecdsa = ["arithmetic", "ecdsa-core/sign", "ecdsa-core/verify", "sha384"] -expose-field = [] +expose-field = ["arithmetic"] hash2curve = ["arithmetic", "elliptic-curve/hash2curve"] jwk = ["elliptic-curve/jwk"] pem = ["elliptic-curve/pem", "ecdsa-core/pem", "pkcs8"]