From a98e242b036a38ad6d36df8f5c482329ce101b0d Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Wed, 13 Mar 2024 20:56:35 +0100 Subject: [PATCH] fix lib25519 build --- benchmarks/Cargo.toml | 2 +- benchmarks/README.md | 14 +++ benchmarks/benches/x25519.rs | 216 +++++++++++++++++------------------ benchmarks/build.rs | 4 +- sys/lib25519/build-native.sh | 42 +++++++ sys/lib25519/build.rs | 2 + sys/pqclean/src/bindings.rs | 2 +- 7 files changed, 171 insertions(+), 111 deletions(-) create mode 100644 benchmarks/README.md create mode 100755 sys/lib25519/build-native.sh diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index edded3b63..9e72ec5f2 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -30,7 +30,7 @@ curve25519-dalek = "4.1.2" # We always link this on linux, even if it may not be built. # We check that in the build instead. -[target.'cfg(all(target_arch = "x86_64", target_os = "linux"))'.dev-dependencies] +[target.'cfg(all(target_arch = "x86_64", target_os = "linux", crypto_lib25519))'.dev-dependencies] lib25519 = { path = "../sys/lib25519" } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 000000000..8929a4629 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,14 @@ +# Libcrux Benchmarks + +This crate is used to benchmark libcrux and compare it to 3rd party implementations. + +## lib25519 +Comparing with lib25519 only works on Linux. +To enable it first build the sys crate + +```bash +cd ../sys/lib25519 +./build-native.sh + +RUSTFLAGS="--cfg crypto_lib25519" cargo criterion --bench x25519 +``` diff --git a/benchmarks/benches/x25519.rs b/benchmarks/benches/x25519.rs index 264fdf74a..a9d9b793d 100644 --- a/benchmarks/benches/x25519.rs +++ b/benchmarks/benches/x25519.rs @@ -9,114 +9,114 @@ fn derive(c: &mut Criterion) { // Comparing libcrux performance for different payload sizes and other implementations. let mut group = c.benchmark_group("x25519/derive"); - // group.bench_function("libcrux", |b| { - // b.iter_batched( - // || { - // let sk1 = randombytes(32); - // let pk1 = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk1).unwrap(); - // let sk2 = randombytes(32); - // (pk1, sk2) - // }, - // |(pk1, sk2)| { - // let _zz = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2).unwrap(); - // }, - // BatchSize::SmallInput, - // ) - // }); - - // group.bench_function("Ring", |b| { - // use ring::{agreement, rand::SystemRandom}; - - // b.iter_batched( - // || { - // let rng = SystemRandom::new(); - // let sk1 = - // agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); - // let pk1 = sk1.compute_public_key().unwrap(); - // let sk2 = - // agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); - - // (pk1, sk2) - // }, - // |(pk1, sk2)| { - // let _zz: Result, ring::error::Unspecified> = agreement::agree_ephemeral( - // sk2, - // &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1), - // |k| Ok(k.to_vec()), - // ) - // .unwrap(); - // }, - // BatchSize::SmallInput, - // ) - // }); - - // #[cfg(all(not(windows), not(target_arch = "wasm32"), not(target_arch = "x86")))] - // group.bench_function("OpenSSL", |b| { - // use openssl::derive::Deriver; - // use openssl::pkey::{Id, PKey}; - // use openssl::pkey_ctx::PkeyCtx; - - // b.iter_batched( - // || { - // let mut ctx = PkeyCtx::new_id(Id::X25519).unwrap(); - // ctx.keygen_init().unwrap(); - // let sk1 = ctx.keygen().unwrap(); - // let pk1 = sk1.raw_public_key().unwrap(); - - // ctx.keygen_init().unwrap(); - // let sk2 = ctx.keygen().unwrap(); - // let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); - // (pk1, sk2) - // }, - // |(pk1, sk2)| { - // let mut deriver = Deriver::new(&sk2).unwrap(); - // deriver.set_peer(&pk1).unwrap(); - // let _zz = deriver.derive_to_vec().unwrap(); - // }, - // BatchSize::SmallInput, - // ) - // }); - - // group.bench_function("Dalek", |b| { - // use rand_core::OsRng; - // use x25519_dalek::{EphemeralSecret, PublicKey}; - - // b.iter_batched( - // || { - // let sk1 = EphemeralSecret::random_from_rng(OsRng); - // let pk1 = PublicKey::from(&sk1); - // let sk2 = EphemeralSecret::random_from_rng(OsRng); - // (pk1, sk2) - // }, - // |(pk1, sk2)| { - // let _zz = sk2.diffie_hellman(&pk1); - // }, - // BatchSize::SmallInput, - // ) - // }); - - // group.bench_function("Dalek Ristretto", |b| { - // use curve25519_dalek::ristretto::RistrettoPoint; - // use curve25519_dalek::scalar::Scalar; - // use rand_core::OsRng; - - // b.iter_batched( - // || { - // let mut sk1_b = [0u8; 32]; - // OsRng.fill_bytes(&mut sk1_b); - // let sk1 = Scalar::from_bytes_mod_order(sk1_b); - // let pk1 = RistrettoPoint::mul_base(&sk1); - // let mut sk2_b = [0u8; 32]; - // OsRng.fill_bytes(&mut sk2_b); - // let sk2 = Scalar::from_bytes_mod_order(sk2_b); - // (pk1, sk2) - // }, - // |(pk1, sk2)| { - // let _zz = pk1 * sk2; - // }, - // BatchSize::SmallInput, - // ) - // }); + group.bench_function("libcrux", |b| { + b.iter_batched( + || { + let sk1 = randombytes(32); + let pk1 = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk1).unwrap(); + let sk2 = randombytes(32); + (pk1, sk2) + }, + |(pk1, sk2)| { + let _zz = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2).unwrap(); + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function("Ring", |b| { + use ring::{agreement, rand::SystemRandom}; + + b.iter_batched( + || { + let rng = SystemRandom::new(); + let sk1 = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + let pk1 = sk1.compute_public_key().unwrap(); + let sk2 = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + (pk1, sk2) + }, + |(pk1, sk2)| { + let _zz: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1), + |k| Ok(k.to_vec()), + ) + .unwrap(); + }, + BatchSize::SmallInput, + ) + }); + + #[cfg(all(not(windows), not(target_arch = "wasm32"), not(target_arch = "x86")))] + group.bench_function("OpenSSL", |b| { + use openssl::derive::Deriver; + use openssl::pkey::{Id, PKey}; + use openssl::pkey_ctx::PkeyCtx; + + b.iter_batched( + || { + let mut ctx = PkeyCtx::new_id(Id::X25519).unwrap(); + ctx.keygen_init().unwrap(); + let sk1 = ctx.keygen().unwrap(); + let pk1 = sk1.raw_public_key().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2 = ctx.keygen().unwrap(); + let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); + (pk1, sk2) + }, + |(pk1, sk2)| { + let mut deriver = Deriver::new(&sk2).unwrap(); + deriver.set_peer(&pk1).unwrap(); + let _zz = deriver.derive_to_vec().unwrap(); + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function("Dalek", |b| { + use rand_core::OsRng; + use x25519_dalek::{EphemeralSecret, PublicKey}; + + b.iter_batched( + || { + let sk1 = EphemeralSecret::random_from_rng(OsRng); + let pk1 = PublicKey::from(&sk1); + let sk2 = EphemeralSecret::random_from_rng(OsRng); + (pk1, sk2) + }, + |(pk1, sk2)| { + let _zz = sk2.diffie_hellman(&pk1); + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function("Dalek Ristretto", |b| { + use curve25519_dalek::ristretto::RistrettoPoint; + use curve25519_dalek::scalar::Scalar; + use rand_core::OsRng; + + b.iter_batched( + || { + let mut sk1_b = [0u8; 32]; + OsRng.fill_bytes(&mut sk1_b); + let sk1 = Scalar::from_bytes_mod_order(sk1_b); + let pk1 = RistrettoPoint::mul_base(&sk1); + let mut sk2_b = [0u8; 32]; + OsRng.fill_bytes(&mut sk2_b); + let sk2 = Scalar::from_bytes_mod_order(sk2_b); + (pk1, sk2) + }, + |(pk1, sk2)| { + let _zz = pk1 * sk2; + }, + BatchSize::SmallInput, + ) + }); #[cfg(all(target_arch = "x86_64", target_os = "linux", crypto_lib25519))] group.bench_function("lib25519", |b| { diff --git a/benchmarks/build.rs b/benchmarks/build.rs index fc89763d8..6468edce0 100644 --- a/benchmarks/build.rs +++ b/benchmarks/build.rs @@ -2,10 +2,12 @@ use std::{env, path::Path}; fn main() { let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let lib_path = format!("{manifest_dir}/../sys/lib25519/lib"); - if Path::new(&format!("{manifest_dir}/../sys/lib25519/lib/lib25519.so")).exists() { + if Path::new(&format!("{lib_path}/lib25519.so")).exists() { // Only build benchmarks against lib25519 when the C library is somewhere // in the path. + println!("cargo:rustc-link-search={lib_path}"); println!("cargo:rustc-cfg=crypto_lib25519"); } } diff --git a/sys/lib25519/build-native.sh b/sys/lib25519/build-native.sh new file mode 100755 index 000000000..710dca106 --- /dev/null +++ b/sys/lib25519/build-native.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -e + +cwd=$(cd $(dirname $0); pwd -P) + +export LD_LIBRARY_PATH="$cwd/lib" +export LIBRARY_PATH="$cwd/lib" +export CPATH="$cwd/include" +export PATH="$cwd/bin:$PATH" + +wget -m https://cpucycles.cr.yp.to/libcpucycles-latest-version.txt +version=$(cat cpucycles.cr.yp.to/libcpucycles-latest-version.txt) +wget -m https://cpucycles.cr.yp.to/libcpucycles-$version.tar.gz +tar -xzf cpucycles.cr.yp.to/libcpucycles-$version.tar.gz +cd libcpucycles-$version + +./configure --prefix=$cwd && make -j8 install + +cd - + +wget -m https://randombytes.cr.yp.to/librandombytes-latest-version.txt +version=$(cat randombytes.cr.yp.to/librandombytes-latest-version.txt) +wget -m https://randombytes.cr.yp.to/librandombytes-$version.tar.gz +tar -xzf randombytes.cr.yp.to/librandombytes-$version.tar.gz +cd librandombytes-$version + +./configure --prefix=$cwd && make -j8 install + +cd - + +wget -m https://lib25519.cr.yp.to/lib25519-latest-version.txt +version=$(cat lib25519.cr.yp.to/lib25519-latest-version.txt) +wget -m https://lib25519.cr.yp.to/lib25519-$version.tar.gz +tar -xzf lib25519.cr.yp.to/lib25519-$version.tar.gz +cd lib25519-$version + +./configure --prefix=$cwd && make -j8 install + +cd - + +rm -rf lib25519* randombytes* cpucycles* librandombytes* libcpucycles* diff --git a/sys/lib25519/build.rs b/sys/lib25519/build.rs index bfa5a1851..c2245b2a8 100644 --- a/sys/lib25519/build.rs +++ b/sys/lib25519/build.rs @@ -3,5 +3,7 @@ use std::env; fn main() { let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); println!("cargo:rustc-link-search={manifest_dir}/lib"); + println!("cargo:rustc-link-lib=cpucycles"); + println!("cargo:rustc-link-lib=randombytes"); println!("cargo:rustc-link-lib=25519"); } diff --git a/sys/pqclean/src/bindings.rs b/sys/pqclean/src/bindings.rs index d50f83289..5f6602af9 100644 --- a/sys/pqclean/src/bindings.rs +++ b/sys/pqclean/src/bindings.rs @@ -1,4 +1,4 @@ -/* automatically generated by rust-bindgen 0.69.2 */ +/* automatically generated by rust-bindgen 0.69.4 */ pub const SHAKE128_RATE: u32 = 168; pub const SHAKE256_RATE: u32 = 136;