diff --git a/Cargo.toml b/Cargo.toml index 9982ba2d2..9ed716a00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "sys/libjade", "sys/platform", "sys/pqclean", + "sys/lib25519", "benchmarks", "fuzz", ] diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index 31ea8ebae..9e72ec5f2 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -23,6 +23,15 @@ sha3 = "0.10" p256 = { version = "0.13", features = ["ecdh"] } # Benchmarking "Ring" ring = "0.17" +# Benchmarking "Dalek X25519" +x25519-dalek = "2.0.1" +# Benchmarking "Dalek Ristretto" +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", crypto_lib25519))'.dev-dependencies] +lib25519 = { path = "../sys/lib25519" } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] criterion = "0.5" 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 3d9a38eb1..a9d9b793d 100644 --- a/benchmarks/benches/x25519.rs +++ b/benchmarks/benches/x25519.rs @@ -2,11 +2,12 @@ use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use libcrux::ecdh; mod util; +use rand::RngCore; use util::*; fn derive(c: &mut Criterion) { // Comparing libcrux performance for different payload sizes and other implementations. - let mut group = c.benchmark_group("x25519 derive"); + let mut group = c.benchmark_group("x25519/derive"); group.bench_function("libcrux", |b| { b.iter_batched( @@ -49,15 +50,42 @@ fn derive(c: &mut Criterion) { ) }); - group.bench_function("RustCrypto", |b| { + #[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_ng::{EphemeralSecret, PublicKey}; + use x25519_dalek::{EphemeralSecret, PublicKey}; b.iter_batched( || { - let sk1 = EphemeralSecret::new(OsRng); + let sk1 = EphemeralSecret::random_from_rng(OsRng); let pk1 = PublicKey::from(&sk1); - let sk2 = EphemeralSecret::new(OsRng); + let sk2 = EphemeralSecret::random_from_rng(OsRng); (pk1, sk2) }, |(pk1, sk2)| { @@ -67,24 +95,46 @@ fn derive(c: &mut Criterion) { ) }); - #[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}; + group.bench_function("Dalek Ristretto", |b| { + use curve25519_dalek::ristretto::RistrettoPoint; + use curve25519_dalek::scalar::Scalar; + use rand_core::OsRng; b.iter_batched( || { - let pk1 = randombytes(32); - let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); - - let sk2 = PKey::generate_x25519().unwrap(); + 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| { + b.iter_batched( + || { + let mut sk1 = [0u8; 32]; + let mut pk1 = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519_keypair(pk1.as_mut_ptr(), sk1.as_mut_ptr()); + } + let sk2 = randombytes(32); (pk1, sk2) }, |(pk1, sk2)| { - let mut deriver = Deriver::new(&sk2).unwrap(); - deriver.set_peer(&pk1).unwrap(); - let _zz = deriver.derive_to_vec().unwrap(); + let mut zz = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519(zz.as_mut_ptr(), pk1.as_ptr(), sk2.as_ptr()); + } }, BatchSize::SmallInput, ) @@ -93,7 +143,7 @@ fn derive(c: &mut Criterion) { fn secret_to_public(c: &mut Criterion) { // Comparing libcrux performance for different payload sizes and other implementations. - let mut group = c.benchmark_group("x25519 secret to public"); + let mut group = c.benchmark_group("x25519/secret to public"); group.bench_function("libcrux", |b| { b.iter_batched( @@ -126,13 +176,30 @@ fn secret_to_public(c: &mut Criterion) { ) }); - group.bench_function("RustCrypto", |b| { + #[cfg(all(not(windows), not(target_arch = "wasm32"), not(target_arch = "x86")))] + group.bench_function("OpenSSL", |b| { + use openssl::pkey::Id; + 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(); + }, + BatchSize::SmallInput, + ) + }); + + group.bench_function("Dalek", |b| { use rand_core::OsRng; - use x25519_dalek_ng::{EphemeralSecret, PublicKey}; + use x25519_dalek::{EphemeralSecret, PublicKey}; b.iter_batched( || { - let sk = EphemeralSecret::new(OsRng); + let sk = EphemeralSecret::random_from_rng(OsRng); sk }, |sk| { @@ -142,19 +209,824 @@ fn secret_to_public(c: &mut Criterion) { ) }); + 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 sk_b = [0u8; 32]; + OsRng.fill_bytes(&mut sk_b); + let sk = Scalar::from_bytes_mod_order(sk_b); + sk + }, + |sk| { + let _pk = RistrettoPoint::mul_base(&sk); + }, + BatchSize::SmallInput, + ) + }); + + #[cfg(all(target_arch = "x86_64", target_os = "linux", crypto_lib25519))] + group.bench_function("lib25519", |b| { + b.iter_batched( + || {}, + |_| { + let mut sk = [0u8; 32]; + let mut pk = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519_keypair(pk.as_mut_ptr(), sk.as_mut_ptr()); + } + }, + BatchSize::SmallInput, + ) + }); +} + +fn nym_outfox_create(c: &mut Criterion) { + // Comparing libcrux performance for different payload sizes and other implementations. + let mut group = c.benchmark_group("x25519/nym outfox create"); + + group.bench_function("libcrux", |b| { + b.iter_batched( + || { + let sk1 = randombytes(32); + let pk1 = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk1).unwrap(); + let sk2a = randombytes(32); + let sk2b = randombytes(32); + let sk2c = randombytes(32); + let sk2d = randombytes(32); + (pk1, sk2a, sk2b, sk2c, sk2d) + }, + |(pk1, sk2a, sk2b, sk2c, sk2d)| { + let _pk2a = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk2a).unwrap(); + let _pk2b = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk2b).unwrap(); + let _pk2c = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk2c).unwrap(); + let _pk2d = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk2d).unwrap(); + let _zza = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2a).unwrap(); + let _zzb = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2b).unwrap(); + let _zzc = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2c).unwrap(); + let _zzd = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2d).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 sk2a = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + let sk2b = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + let sk2c = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + let sk2d = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + (pk1, sk2a, sk2b, sk2c, sk2d) + }, + |(pk1, sk2a, sk2b, sk2c, sk2d)| { + let _pk2a = sk2a.compute_public_key().unwrap(); + let _pk2b = sk2b.compute_public_key().unwrap(); + let _pk2c = sk2c.compute_public_key().unwrap(); + let _pk2d = sk2d.compute_public_key().unwrap(); + let _zza: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2a, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |k| Ok(k.to_vec()), + ) + .unwrap(); + let _zzb: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2b, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |k| Ok(k.to_vec()), + ) + .unwrap(); + let _zzc: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2c, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |k| Ok(k.to_vec()), + ) + .unwrap(); + let _zzd: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2d, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |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::pkey::PKey; + use openssl::derive::Deriver; + use openssl::pkey::{Id, PKey}; + use openssl::pkey_ctx::PkeyCtx; b.iter_batched( - || {}, - |()| { - let _pk = PKey::generate_x25519().unwrap(); + || { + let mut ctx = PkeyCtx::new_id(Id::X25519).unwrap(); + ctx.keygen_init().unwrap(); + let pkey = ctx.keygen().unwrap(); + let pk1 = pkey.raw_public_key().unwrap(); + let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); + + pk1 + }, + |pk1| { + let mut ctx = PkeyCtx::new_id(Id::X25519).unwrap(); + ctx.keygen_init().unwrap(); + let sk2a = ctx.keygen().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2b = ctx.keygen().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2c = ctx.keygen().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2d = ctx.keygen().unwrap(); + + let mut deriver1 = Deriver::new(&sk2a).unwrap(); + deriver1.set_peer(&pk1).unwrap(); + let _zz1 = deriver1.derive_to_vec().unwrap(); + let mut deriver2 = Deriver::new(&sk2b).unwrap(); + deriver2.set_peer(&pk1).unwrap(); + let _zz2 = deriver2.derive_to_vec().unwrap(); + let mut deriver3 = Deriver::new(&sk2c).unwrap(); + deriver3.set_peer(&pk1).unwrap(); + let _zz3 = deriver3.derive_to_vec().unwrap(); + let mut deriver4 = Deriver::new(&sk2d).unwrap(); + deriver4.set_peer(&pk1).unwrap(); + let _zz4 = deriver4.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 sk2a = EphemeralSecret::random_from_rng(OsRng); + let sk2b = EphemeralSecret::random_from_rng(OsRng); + let sk2c = EphemeralSecret::random_from_rng(OsRng); + let sk2d = EphemeralSecret::random_from_rng(OsRng); + (pk1, sk2a, sk2b, sk2c, sk2d) + }, + |(pk1, sk2a, sk2b, sk2c, sk2d)| { + let _pk2a = PublicKey::from(&sk2a); + let _pk2b = PublicKey::from(&sk2b); + let _pk2c = PublicKey::from(&sk2c); + let _pk2d = PublicKey::from(&sk2d); + let _zza = sk2a.diffie_hellman(&pk1); + let _zzb = sk2b.diffie_hellman(&pk1); + let _zzc = sk2c.diffie_hellman(&pk1); + let _zzd = sk2d.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 sk2a = Scalar::from_bytes_mod_order(sk2_b); + let sk2b = Scalar::from_bytes_mod_order(sk2_b); + let sk2c = Scalar::from_bytes_mod_order(sk2_b); + let sk2d = Scalar::from_bytes_mod_order(sk2_b); + (pk1, sk2a, sk2b, sk2c, sk2d) + }, + |(pk1, sk2a, sk2b, sk2c, sk2d)| { + let _pk2a = RistrettoPoint::mul_base(&sk2a); + let _pk2b = RistrettoPoint::mul_base(&sk2b); + let _pk2c = RistrettoPoint::mul_base(&sk2c); + let _pk2d = RistrettoPoint::mul_base(&sk2d); + let _zza = pk1 * sk2a; + let _zzb = pk1 * sk2b; + let _zzc = pk1 * sk2c; + let _zzd = pk1 * sk2d; + }, + BatchSize::SmallInput, + ) + }); + + #[cfg(all(target_arch = "x86_64", target_os = "linux", crypto_lib25519))] + group.bench_function("lib25519", |b| { + b.iter_batched( + || { + let mut sk1 = [0u8; 32]; + let mut pk1 = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519_keypair(pk1.as_mut_ptr(), sk1.as_mut_ptr()); + } + let sk2a = randombytes(32); + let sk2b = randombytes(32); + let sk2c = randombytes(32); + let sk2d = randombytes(32); + (pk1, sk2a, sk2b, sk2c, sk2d) + }, + |(pk1, sk2a, sk2b, sk2c, sk2d)| { + let mut pks = [0u8; 32 * 8]; + let mut sks = [0u8; 32 * 8]; + let mut zzs = [0u8; 32 * 8]; + pks[..32].copy_from_slice(&pk1); + pks[32..64].copy_from_slice(&pk1); + pks[64..96].copy_from_slice(&pk1); + pks[96..128].copy_from_slice(&pk1); + pks[128..160].copy_from_slice(&pk1); + pks[160..192].copy_from_slice(&pk1); + pks[192..224].copy_from_slice(&pk1); + pks[224..].copy_from_slice(&pk1); + sks[..32].copy_from_slice(&sk2a); + sks[32..64].copy_from_slice(&sk2b); + sks[64..96].copy_from_slice(&sk2c); + sks[96..128].copy_from_slice(&sk2d); + sks[128..160].copy_from_slice(&sk2a); + sks[160..192].copy_from_slice(&sk2b); + sks[192..224].copy_from_slice(&sk2c); + sks[224..].copy_from_slice(&sk2d); + unsafe { + lib25519::lib25519_nPbatch_montgomery25519( + zzs.as_mut_ptr(), + pks.as_ptr(), + sks.as_ptr(), + 8, + ); + } + }, + BatchSize::SmallInput, + ) + }); +} + +fn nym_outfox_process(c: &mut Criterion) { + // Comparing libcrux performance for different payload sizes and other implementations. + let mut group = c.benchmark_group("x25519/nym outfox process"); + + 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(); + let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); + + let sk2 = PKey::generate_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| { + b.iter_batched( + || { + let mut sk1 = [0u8; 32]; + let mut pk1 = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519_keypair(pk1.as_mut_ptr(), sk1.as_mut_ptr()); + } + let sk2 = randombytes(32); + (pk1, sk2) + }, + |(pk1, sk2)| { + let mut zz = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519(zz.as_mut_ptr(), pk1.as_ptr(), sk2.as_ptr()); + } + }, + BatchSize::SmallInput, + ) + }); +} + +fn nym_sphinx_create(c: &mut Criterion) { + // Comparing libcrux performance for different payload sizes and other implementations. + let mut group = c.benchmark_group("x25519/nym sphinx create"); + + 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 _pk2a = ecdh::secret_to_public(ecdh::Algorithm::X25519, &sk2).unwrap(); + let zza = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2).unwrap(); + let _pk2b = ecdh::secret_to_public(ecdh::Algorithm::X25519, &zza).unwrap(); + let zzb = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &zza).unwrap(); + let _pk2c = ecdh::secret_to_public(ecdh::Algorithm::X25519, &zzb).unwrap(); + let zzc = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &zzb).unwrap(); + let _pk2d = ecdh::secret_to_public(ecdh::Algorithm::X25519, &zzc).unwrap(); + let _zzd = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &zzc).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 sk2a = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + let sk2b = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + let sk2c = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + let sk2d = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + (pk1, sk2a, sk2b, sk2c, sk2d) + }, + |(pk1, sk2a, sk2b, sk2c, sk2d)| { + let _pk2a = sk2a.compute_public_key().unwrap(); + let _zza: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2a, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |k| Ok(k.to_vec()), + ) + .unwrap(); + let _pk2b = sk2b.compute_public_key().unwrap(); + let _zzb: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2b, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |k| Ok(k.to_vec()), + ) + .unwrap(); + let _pk2c = sk2c.compute_public_key().unwrap(); + let _zzc: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2c, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |k| Ok(k.to_vec()), + ) + .unwrap(); + let _pk2d = sk2d.compute_public_key().unwrap(); + let _zzd: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2d, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1.clone()), + |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(); + let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); + + pk1 + }, + |pk1| { + let mut ctx = PkeyCtx::new_id(Id::X25519).unwrap(); + ctx.keygen_init().unwrap(); + let sk2a = ctx.keygen().unwrap(); + + let mut deriver1 = Deriver::new(&sk2a).unwrap(); + deriver1.set_peer(&pk1).unwrap(); + let _zz1 = deriver1.derive_to_vec().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2b = ctx.keygen().unwrap(); + + let mut deriver2 = Deriver::new(&sk2b).unwrap(); + deriver2.set_peer(&pk1).unwrap(); + let _zz2 = deriver2.derive_to_vec().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2c = ctx.keygen().unwrap(); + + let mut deriver3 = Deriver::new(&sk2c).unwrap(); + deriver3.set_peer(&pk1).unwrap(); + let _zz3 = deriver3.derive_to_vec().unwrap(); + + ctx.keygen_init().unwrap(); + let sk2d = ctx.keygen().unwrap(); + + let mut deriver4 = Deriver::new(&sk2d).unwrap(); + deriver4.set_peer(&pk1).unwrap(); + let _zz4 = deriver4.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, sk2a)| { + let _pk2a = PublicKey::from(&sk2a); + let _zza = sk2a.diffie_hellman(&pk1); + let sk2b = EphemeralSecret::random_from_rng(OsRng); + let _pk2b = PublicKey::from(&sk2b); + let _zza = sk2b.diffie_hellman(&pk1); + let sk2c = EphemeralSecret::random_from_rng(OsRng); + let _pk2c = PublicKey::from(&sk2c); + let _zzc = sk2c.diffie_hellman(&pk1); + let sk2d = EphemeralSecret::random_from_rng(OsRng); + let _pk2d = PublicKey::from(&sk2d); + let _zzd = sk2d.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 sk2a = Scalar::from_bytes_mod_order(sk2_b); + (pk1, sk2a) + }, + |(pk1, sk2a)| { + let _pk2a = RistrettoPoint::mul_base(&sk2a); + let zza = (pk1 * sk2a).compress().to_bytes(); + let sk2b = Scalar::from_bytes_mod_order(zza); + let _pk2b = RistrettoPoint::mul_base(&sk2b); + let zzb = (pk1 * sk2b).compress().to_bytes(); + let sk2c = Scalar::from_bytes_mod_order(zzb); + let _pk2c = RistrettoPoint::mul_base(&sk2c); + let zzc = (pk1 * sk2c).compress().to_bytes(); + let sk2d = Scalar::from_bytes_mod_order(zzc); + let _pk2d = RistrettoPoint::mul_base(&sk2d); + let _zzd = pk1 * sk2d; + }, + BatchSize::SmallInput, + ) + }); + + #[cfg(all(target_arch = "x86_64", target_os = "linux", crypto_lib25519))] + group.bench_function("lib25519", |b| { + b.iter_batched( + || { + let mut sk1 = [0u8; 32]; + let mut pk1 = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519_keypair(pk1.as_mut_ptr(), sk1.as_mut_ptr()); + } + let sk2 = randombytes(32); + sk2 + }, + |sk2| { + let mut zz1 = [0u8; 32]; + let mut zz2 = [0u8; 32]; + let mut zz3 = [0u8; 32]; + let mut zz4 = [0u8; 32]; + let mut pk1 = [0u8; 32]; + let mut pk2 = [0u8; 32]; + let mut pk3 = [0u8; 32]; + let mut pk4 = [0u8; 32]; + unsafe { + lib25519::lib25519_nG_montgomery25519(pk1.as_mut_ptr(), sk2.as_ptr()); + lib25519::lib25519_dh_x25519(zz1.as_mut_ptr(), pk1.as_ptr(), sk2.as_ptr()); + } + unsafe { + lib25519::lib25519_nG_montgomery25519(pk2.as_mut_ptr(), zz1.as_ptr()); + lib25519::lib25519_dh_x25519(zz2.as_mut_ptr(), pk1.as_ptr(), zz1.as_ptr()); + } + unsafe { + lib25519::lib25519_nG_montgomery25519(pk3.as_mut_ptr(), zz3.as_ptr()); + lib25519::lib25519_dh_x25519(zz3.as_mut_ptr(), pk1.as_ptr(), zz2.as_ptr()); + } + unsafe { + lib25519::lib25519_nG_montgomery25519(pk4.as_mut_ptr(), zz3.as_ptr()); + lib25519::lib25519_dh_x25519(zz4.as_mut_ptr(), pk1.as_ptr(), zz3.as_ptr()); + } + }, + BatchSize::SmallInput, + ) + }); +} + +fn nym_sphinx_process(c: &mut Criterion) { + // Comparing libcrux performance for different payload sizes and other implementations. + let mut group = c.benchmark_group("x25519/nym sphinx process"); + + 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 _zz1 = ecdh::derive(ecdh::Algorithm::X25519, &pk1, &sk2).unwrap(); + let _zz2 = 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(); + let pk2 = sk2.compute_public_key().unwrap(); + + let sk3 = + agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); + + (pk1, pk2, sk2, sk3) + }, + |(pk1, pk2, sk2, sk3)| { + let _zz: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk2, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk1), + |k| Ok(k.to_vec()), + ) + .unwrap(); + + let _zz2: Result, ring::error::Unspecified> = agreement::agree_ephemeral( + sk3, + &agreement::UnparsedPublicKey::new(&agreement::X25519, pk2), + |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(); + let pk1 = PKey::public_key_from_raw_bytes(&pk1, Id::X25519).unwrap(); + + ctx.keygen_init().unwrap(); + let sk2 = ctx.keygen().unwrap(); + let pk2 = sk2.raw_public_key().unwrap(); + let pk2 = PKey::public_key_from_raw_bytes(&pk2, Id::X25519).unwrap(); + + (sk1, pk1, sk2, pk2) + }, + |(sk1, pk1, sk2, pk2)| { + let mut deriver = Deriver::new(&sk2).unwrap(); + deriver.set_peer(&pk1).unwrap(); + let _zz1 = deriver.derive_to_vec().unwrap(); + let mut deriver = Deriver::new(&sk1).unwrap(); + deriver.set_peer(&pk2).unwrap(); + let _zz2 = 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); + let pk2 = PublicKey::from(&sk2); + (sk1, pk1, sk2, pk2) + }, + |(sk1, pk1, sk2, pk2)| { + let _zz = sk2.diffie_hellman(&pk1); + let _zz2 = sk1.diffie_hellman(&pk2); + }, + 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); + let pk2 = RistrettoPoint::mul_base(&sk2); + (sk1, pk1, sk2, pk2) + }, + |(sk1, pk1, sk2, pk2)| { + let _zz = pk1 * sk2; + let _zz2 = pk2 * sk1; + }, + BatchSize::SmallInput, + ) + }); + + #[cfg(all(target_arch = "x86_64", target_os = "linux", crypto_lib25519))] + group.bench_function("lib25519", |b| { + b.iter_batched( + || { + let mut sk1 = [0u8; 32]; + let mut pk1 = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519_keypair(pk1.as_mut_ptr(), sk1.as_mut_ptr()); + } + let sk2 = randombytes(32); + (pk1, sk2) + }, + |(pk1, sk2)| { + let mut zz = [0u8; 32]; + let mut zz2 = [0u8; 32]; + unsafe { + lib25519::lib25519_dh_x25519(zz.as_mut_ptr(), pk1.as_ptr(), sk2.as_ptr()); + lib25519::lib25519_dh_x25519(zz2.as_mut_ptr(), pk1.as_ptr(), sk2.as_ptr()); + } }, BatchSize::SmallInput, ) }); } -criterion_group!(benches, derive, secret_to_public); +criterion_group!( + benches, + derive, + secret_to_public, + nym_outfox_create, + nym_outfox_process, + nym_sphinx_create, + nym_sphinx_process +); criterion_main!(benches); diff --git a/benchmarks/build.rs b/benchmarks/build.rs new file mode 100644 index 000000000..6468edce0 --- /dev/null +++ b/benchmarks/build.rs @@ -0,0 +1,13 @@ +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!("{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/Cargo.toml b/sys/lib25519/Cargo.toml new file mode 100644 index 000000000..1ec2037e6 --- /dev/null +++ b/sys/lib25519/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "lib25519" +version.workspace = true +edition.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +description = "sys crate for lib25519 on linux." + +[dependencies] +libc = "0.2" + +[build-dependencies] +cc = { version = "1.0", features = ["parallel"] } +bindgen = { version = "0.69", optional = true } +pkg-config = "0.3" 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 new file mode 100644 index 000000000..c2245b2a8 --- /dev/null +++ b/sys/lib25519/build.rs @@ -0,0 +1,9 @@ +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/lib25519/src/bindings.rs b/sys/lib25519/src/bindings.rs new file mode 100644 index 000000000..51a3f43a8 --- /dev/null +++ b/sys/lib25519/src/bindings.rs @@ -0,0 +1,596 @@ +/* automatically generated by rust-bindgen 0.59.1 */ + +pub const lib25519_version: &'static [u8; 9usize] = b"20230630\0"; +pub const lib25519_arch: &'static [u8; 6usize] = b"amd64\0"; +pub const lib25519_verify_BYTES: u32 = 32; +pub const lib25519_verify_32_BYTES: u32 = 32; +pub const lib25519_hashblocks_STATEBYTES: u32 = 64; +pub const lib25519_hashblocks_BLOCKBYTES: u32 = 128; +pub const lib25519_hashblocks_sha512_STATEBYTES: u32 = 64; +pub const lib25519_hashblocks_sha512_BLOCKBYTES: u32 = 128; +pub const lib25519_hash_BYTES: u32 = 64; +pub const lib25519_hash_sha512_BYTES: u32 = 64; +pub const lib25519_pow_BYTES: u32 = 32; +pub const lib25519_pow_inv25519_BYTES: u32 = 32; +pub const lib25519_powbatch_BYTES: u32 = 32; +pub const lib25519_powbatch_inv25519_BYTES: u32 = 32; +pub const lib25519_nP_SCALARBYTES: u32 = 32; +pub const lib25519_nP_POINTBYTES: u32 = 32; +pub const lib25519_nP_montgomery25519_SCALARBYTES: u32 = 32; +pub const lib25519_nP_montgomery25519_POINTBYTES: u32 = 32; +pub const lib25519_nPbatch_SCALARBYTES: u32 = 32; +pub const lib25519_nPbatch_POINTBYTES: u32 = 32; +pub const lib25519_nPbatch_montgomery25519_SCALARBYTES: u32 = 32; +pub const lib25519_nPbatch_montgomery25519_POINTBYTES: u32 = 32; +pub const lib25519_nG_SCALARBYTES: u32 = 32; +pub const lib25519_nG_POINTBYTES: u32 = 32; +pub const lib25519_nG_merged25519_SCALARBYTES: u32 = 32; +pub const lib25519_nG_merged25519_POINTBYTES: u32 = 32; +pub const lib25519_nG_montgomery25519_SCALARBYTES: u32 = 32; +pub const lib25519_nG_montgomery25519_POINTBYTES: u32 = 32; +pub const lib25519_mGnP_MBYTES: u32 = 32; +pub const lib25519_mGnP_NBYTES: u32 = 64; +pub const lib25519_mGnP_PBYTES: u32 = 32; +pub const lib25519_mGnP_OUTPUTBYTES: u32 = 33; +pub const lib25519_mGnP_ed25519_MBYTES: u32 = 32; +pub const lib25519_mGnP_ed25519_NBYTES: u32 = 64; +pub const lib25519_mGnP_ed25519_PBYTES: u32 = 32; +pub const lib25519_mGnP_ed25519_OUTPUTBYTES: u32 = 33; +pub const lib25519_multiscalar_SCALARBYTES: u32 = 32; +pub const lib25519_multiscalar_POINTBYTES: u32 = 32; +pub const lib25519_multiscalar_OUTPUTBYTES: u32 = 33; +pub const lib25519_multiscalar_ed25519_SCALARBYTES: u32 = 32; +pub const lib25519_multiscalar_ed25519_POINTBYTES: u32 = 32; +pub const lib25519_multiscalar_ed25519_OUTPUTBYTES: u32 = 33; +pub const lib25519_dh_SECRETKEYBYTES: u32 = 32; +pub const lib25519_dh_PUBLICKEYBYTES: u32 = 32; +pub const lib25519_dh_BYTES: u32 = 32; +pub const lib25519_dh_x25519_SECRETKEYBYTES: u32 = 32; +pub const lib25519_dh_x25519_PUBLICKEYBYTES: u32 = 32; +pub const lib25519_dh_x25519_BYTES: u32 = 32; +pub const lib25519_sign_SECRETKEYBYTES: u32 = 64; +pub const lib25519_sign_PUBLICKEYBYTES: u32 = 32; +pub const lib25519_sign_BYTES: u32 = 64; +pub const lib25519_sign_ed25519_SECRETKEYBYTES: u32 = 64; +pub const lib25519_sign_ed25519_PUBLICKEYBYTES: u32 = 32; +pub const lib25519_sign_ed25519_BYTES: u32 = 64; +extern "C" { + pub fn lib25519_cpuid(arg1: *mut ::std::os::raw::c_uint, arg2: ::std::os::raw::c_longlong); +} +extern "C" { + pub fn lib25519_verify_32( + arg1: *const ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn lib25519_dispatch_verify_32( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *const ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ) -> ::std::os::raw::c_int, + >; +} +extern "C" { + pub fn lib25519_verify_32_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_verify_32_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_verify_32_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_verify_32_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_verify_32() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_hashblocks_sha512( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn lib25519_dispatch_hashblocks_sha512( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: ::std::os::raw::c_longlong, + ) -> ::std::os::raw::c_int, + >; +} +extern "C" { + pub fn lib25519_hashblocks_sha512_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_hashblocks_sha512_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_hashblocks_sha512_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_hashblocks_sha512_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_hashblocks_sha512() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_hash_sha512( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: ::std::os::raw::c_longlong, + ); +} +extern "C" { + pub fn lib25519_dispatch_hash_sha512( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: ::std::os::raw::c_longlong, + ), + >; +} +extern "C" { + pub fn lib25519_hash_sha512_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_hash_sha512_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_hash_sha512_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_hash_sha512_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_hash_sha512() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_pow_inv25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_pow_inv25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_pow_inv25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_pow_inv25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_pow_inv25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_pow_inv25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_pow_inv25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_powbatch_inv25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: ::std::os::raw::c_longlong, + ); +} +extern "C" { + pub fn lib25519_dispatch_powbatch_inv25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: ::std::os::raw::c_longlong, + ), + >; +} +extern "C" { + pub fn lib25519_powbatch_inv25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_powbatch_inv25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_powbatch_inv25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_powbatch_inv25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_powbatch_inv25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_nP_montgomery25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_nP_montgomery25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_nP_montgomery25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_nP_montgomery25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nP_montgomery25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nP_montgomery25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_nP_montgomery25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_nPbatch_montgomery25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + ); +} +extern "C" { + pub fn lib25519_dispatch_nPbatch_montgomery25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + ), + >; +} +extern "C" { + pub fn lib25519_nPbatch_montgomery25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_nPbatch_montgomery25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nPbatch_montgomery25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nPbatch_montgomery25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_nPbatch_montgomery25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_nG_merged25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_nG_merged25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_nG_merged25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_nG_merged25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nG_merged25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nG_merged25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_nG_merged25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_nG_montgomery25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_nG_montgomery25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_nG_montgomery25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_nG_montgomery25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nG_montgomery25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_nG_montgomery25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_nG_montgomery25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_mGnP_ed25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + arg4: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_mGnP_ed25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + arg4: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_mGnP_ed25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_mGnP_ed25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_mGnP_ed25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_mGnP_ed25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_mGnP_ed25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_multiscalar_ed25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + ); +} +extern "C" { + pub fn lib25519_dispatch_multiscalar_ed25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + ), + >; +} +extern "C" { + pub fn lib25519_multiscalar_ed25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_multiscalar_ed25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_multiscalar_ed25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_multiscalar_ed25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_multiscalar_ed25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_dh_x25519_keypair( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_dh_x25519_keypair( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_dh_x25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_dh_x25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *const ::std::os::raw::c_uchar, + arg3: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_dh_x25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dh_x25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_dh_x25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_dh_x25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_dh_x25519() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn lib25519_sign_ed25519_keypair( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_sign_ed25519_keypair( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_sign_ed25519( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_longlong, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + arg5: *const ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn lib25519_dispatch_sign_ed25519( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_longlong, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + arg5: *const ::std::os::raw::c_uchar, + ), + >; +} +extern "C" { + pub fn lib25519_sign_ed25519_open( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_longlong, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + arg5: *const ::std::os::raw::c_uchar, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn lib25519_dispatch_sign_ed25519_open( + arg1: ::std::os::raw::c_longlong, + ) -> ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::std::os::raw::c_uchar, + arg2: *mut ::std::os::raw::c_longlong, + arg3: *const ::std::os::raw::c_uchar, + arg4: ::std::os::raw::c_longlong, + arg5: *const ::std::os::raw::c_uchar, + ) -> ::std::os::raw::c_int, + >; +} +extern "C" { + pub fn lib25519_sign_ed25519_implementation() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_sign_ed25519_compiler() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_sign_ed25519_implementation( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_dispatch_sign_ed25519_compiler( + arg1: ::std::os::raw::c_longlong, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn lib25519_numimpl_sign_ed25519() -> ::std::os::raw::c_longlong; +} diff --git a/sys/lib25519/src/lib.rs b/sys/lib25519/src/lib.rs new file mode 100644 index 000000000..05d92f297 --- /dev/null +++ b/sys/lib25519/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("./bindings.rs");