mirror of
https://github.com/saymrwulf/fips205-source.git
synced 2026-09-10 21:01:02 +00:00
prep update
This commit is contained in:
parent
fca844d470
commit
8c03d1f9c3
12 changed files with 531 additions and 490 deletions
|
|
@ -1,8 +1,10 @@
|
||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
use fips205::traits::{KeyGen, Signer, Verifier};
|
use fips205::traits::{KeyGen, Signer, Verifier};
|
||||||
use fips205::{slh_dsa_sha2_128s, slh_dsa_shake_128s, slh_dsa_sha2_128f, slh_dsa_shake_128f,
|
use fips205::{
|
||||||
slh_dsa_sha2_192s, slh_dsa_shake_192s, slh_dsa_sha2_192f, slh_dsa_shake_192f,
|
slh_dsa_sha2_128f, slh_dsa_sha2_128s, slh_dsa_sha2_192f, slh_dsa_sha2_192s, slh_dsa_sha2_256f,
|
||||||
slh_dsa_sha2_256s, slh_dsa_shake_256s, slh_dsa_sha2_256f, slh_dsa_shake_256f};
|
slh_dsa_sha2_256s, slh_dsa_shake_128f, slh_dsa_shake_128s, slh_dsa_shake_192f,
|
||||||
|
slh_dsa_shake_192s, slh_dsa_shake_256f, slh_dsa_shake_256s,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
|
|
@ -49,31 +51,79 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
c.bench_function("shake_192s keygen", |b| b.iter(|| slh_dsa_shake_192s::KG::try_keygen_vt()));
|
c.bench_function("shake_192s keygen", |b| b.iter(|| slh_dsa_shake_192s::KG::try_keygen_vt()));
|
||||||
c.bench_function("shake_256s keygen", |b| b.iter(|| slh_dsa_shake_256s::KG::try_keygen_vt()));
|
c.bench_function("shake_256s keygen", |b| b.iter(|| slh_dsa_shake_256s::KG::try_keygen_vt()));
|
||||||
//
|
//
|
||||||
c.bench_function("sha2_128f sign ", |b| b.iter(|| sk_sha2_128f.try_sign_ct(&message, randomize)));
|
c.bench_function("sha2_128f sign ", |b| {
|
||||||
c.bench_function("sha2_192f sign ", |b| b.iter(|| sk_sha2_192f.try_sign_ct(&message, randomize)));
|
b.iter(|| sk_sha2_128f.try_sign_ct(&message, randomize))
|
||||||
c.bench_function("sha2_256f sign ", |b| b.iter(|| sk_sha2_256f.try_sign_ct(&message, randomize)));
|
});
|
||||||
c.bench_function("shake_128f sign ", |b| b.iter(|| sk_shake_128f.try_sign_ct(&message, randomize)));
|
c.bench_function("sha2_192f sign ", |b| {
|
||||||
c.bench_function("shake_192f sign ", |b| b.iter(|| sk_shake_192f.try_sign_ct(&message, randomize)));
|
b.iter(|| sk_sha2_192f.try_sign_ct(&message, randomize))
|
||||||
c.bench_function("shake_256f sign ", |b| b.iter(|| sk_shake_256f.try_sign_ct(&message, randomize)));
|
});
|
||||||
c.bench_function("sha2_128s sign ", |b| b.iter(|| sk_sha2_128s.try_sign_ct(&message, randomize)));
|
c.bench_function("sha2_256f sign ", |b| {
|
||||||
c.bench_function("sha2_192s sign ", |b| b.iter(|| sk_sha2_192s.try_sign_ct(&message, randomize)));
|
b.iter(|| sk_sha2_256f.try_sign_ct(&message, randomize))
|
||||||
c.bench_function("sha2_256s sign ", |b| b.iter(|| sk_sha2_256s.try_sign_ct(&message, randomize)));
|
});
|
||||||
c.bench_function("shake_128s sign ", |b| b.iter(|| sk_shake_128s.try_sign_ct(&message, randomize)));
|
c.bench_function("shake_128f sign ", |b| {
|
||||||
c.bench_function("shake_192s sign ", |b| b.iter(|| sk_shake_192s.try_sign_ct(&message, randomize)));
|
b.iter(|| sk_shake_128f.try_sign_ct(&message, randomize))
|
||||||
c.bench_function("shake_256s sign ", |b| b.iter(|| sk_shake_256s.try_sign_ct(&message, randomize)));
|
});
|
||||||
|
c.bench_function("shake_192f sign ", |b| {
|
||||||
|
b.iter(|| sk_shake_192f.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_256f sign ", |b| {
|
||||||
|
b.iter(|| sk_shake_256f.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("sha2_128s sign ", |b| {
|
||||||
|
b.iter(|| sk_sha2_128s.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("sha2_192s sign ", |b| {
|
||||||
|
b.iter(|| sk_sha2_192s.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("sha2_256s sign ", |b| {
|
||||||
|
b.iter(|| sk_sha2_256s.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_128s sign ", |b| {
|
||||||
|
b.iter(|| sk_shake_128s.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_192s sign ", |b| {
|
||||||
|
b.iter(|| sk_shake_192s.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_256s sign ", |b| {
|
||||||
|
b.iter(|| sk_shake_256s.try_sign_ct(&message, randomize))
|
||||||
|
});
|
||||||
//
|
//
|
||||||
c.bench_function("sha2_128f verify", |b| b.iter(|| pk_sha2_128f.try_verify_vt(&message, &sig_sha2_128f)));
|
c.bench_function("sha2_128f verify", |b| {
|
||||||
c.bench_function("sha2_192f verify", |b| b.iter(|| pk_sha2_192f.try_verify_vt(&message, &sig_sha2_192f)));
|
b.iter(|| pk_sha2_128f.try_verify_vt(&message, &sig_sha2_128f))
|
||||||
c.bench_function("sha2_256f verify", |b| b.iter(|| pk_sha2_256f.try_verify_vt(&message, &sig_sha2_256f)));
|
});
|
||||||
c.bench_function("shake_128f verify", |b| b.iter(|| pk_shake_128f.try_verify_vt(&message, &sig_shake_128f)));
|
c.bench_function("sha2_192f verify", |b| {
|
||||||
c.bench_function("shake_192f verify", |b| b.iter(|| pk_shake_192f.try_verify_vt(&message, &sig_shake_192f)));
|
b.iter(|| pk_sha2_192f.try_verify_vt(&message, &sig_sha2_192f))
|
||||||
c.bench_function("shake_256f verify", |b| b.iter(|| pk_shake_256f.try_verify_vt(&message, &sig_shake_256f)));
|
});
|
||||||
c.bench_function("sha2_128s verify", |b| b.iter(|| pk_sha2_128s.try_verify_vt(&message, &sig_sha2_128s)));
|
c.bench_function("sha2_256f verify", |b| {
|
||||||
c.bench_function("sha2_192s verify", |b| b.iter(|| pk_sha2_192s.try_verify_vt(&message, &sig_sha2_192s)));
|
b.iter(|| pk_sha2_256f.try_verify_vt(&message, &sig_sha2_256f))
|
||||||
c.bench_function("sha2_256s verify", |b| b.iter(|| pk_sha2_256s.try_verify_vt(&message, &sig_sha2_256s)));
|
});
|
||||||
c.bench_function("shake_128s verify", |b| b.iter(|| pk_shake_128s.try_verify_vt(&message, &sig_shake_128s)));
|
c.bench_function("shake_128f verify", |b| {
|
||||||
c.bench_function("shake_192s verify", |b| b.iter(|| pk_shake_192s.try_verify_vt(&message, &sig_shake_192s)));
|
b.iter(|| pk_shake_128f.try_verify_vt(&message, &sig_shake_128f))
|
||||||
c.bench_function("shake_256s verify", |b| b.iter(|| pk_shake_256s.try_verify_vt(&message, &sig_shake_256s)));
|
});
|
||||||
|
c.bench_function("shake_192f verify", |b| {
|
||||||
|
b.iter(|| pk_shake_192f.try_verify_vt(&message, &sig_shake_192f))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_256f verify", |b| {
|
||||||
|
b.iter(|| pk_shake_256f.try_verify_vt(&message, &sig_shake_256f))
|
||||||
|
});
|
||||||
|
c.bench_function("sha2_128s verify", |b| {
|
||||||
|
b.iter(|| pk_sha2_128s.try_verify_vt(&message, &sig_sha2_128s))
|
||||||
|
});
|
||||||
|
c.bench_function("sha2_192s verify", |b| {
|
||||||
|
b.iter(|| pk_sha2_192s.try_verify_vt(&message, &sig_sha2_192s))
|
||||||
|
});
|
||||||
|
c.bench_function("sha2_256s verify", |b| {
|
||||||
|
b.iter(|| pk_sha2_256s.try_verify_vt(&message, &sig_sha2_256s))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_128s verify", |b| {
|
||||||
|
b.iter(|| pk_shake_128s.try_verify_vt(&message, &sig_shake_128s))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_192s verify", |b| {
|
||||||
|
b.iter(|| pk_shake_192s.try_verify_vt(&message, &sig_shake_192s))
|
||||||
|
});
|
||||||
|
c.bench_function("shake_256s verify", |b| {
|
||||||
|
b.iter(|| pk_shake_256s.try_verify_vt(&message, &sig_shake_256s))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(benches, criterion_benchmark);
|
criterion_group!(benches, criterion_benchmark);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::convert::TryInto;
|
|
||||||
use fips205;
|
use fips205;
|
||||||
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ pub extern "C" fn slh_dsa_sha2_128f_keygen(
|
||||||
) -> u8 {
|
) -> u8 {
|
||||||
//use fips205::traits::{KeyGen, SerDes};
|
//use fips205::traits::{KeyGen, SerDes};
|
||||||
|
|
||||||
let (Some(public_out), Some(private_out)) = (public_out, private_out) else {
|
let (Some(public_out), Some(private_out)) = (public_out, private_out) else {
|
||||||
return SLH_DSA_NULL_PTR_ERROR;
|
return SLH_DSA_NULL_PTR_ERROR;
|
||||||
};
|
};
|
||||||
let Ok((pk, sk)) = fips205::slh_dsa_sha2_128f::KG::try_keygen_vt() else {
|
let Ok((pk, sk)) = fips205::slh_dsa_sha2_128f::KG::try_keygen_vt() else {
|
||||||
|
|
@ -58,8 +58,7 @@ pub extern "C" fn slh_dsa_sha2_128f_keygen(
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn slh_dsa_sha2_128f_sign(
|
pub extern "C" fn slh_dsa_sha2_128f_sign(
|
||||||
message_buf: *const u8,
|
message_buf: *const u8, message_len: c_int,
|
||||||
message_len: c_int,
|
|
||||||
private_key: Option<&mut slh_dsa_sha2_128f_private_key>,
|
private_key: Option<&mut slh_dsa_sha2_128f_private_key>,
|
||||||
signature_out: Option<&mut slh_dsa_sha2_128f_signature>,
|
signature_out: Option<&mut slh_dsa_sha2_128f_signature>,
|
||||||
) -> u8 {
|
) -> u8 {
|
||||||
|
|
@ -67,9 +66,12 @@ pub extern "C" fn slh_dsa_sha2_128f_sign(
|
||||||
return SLH_DSA_NULL_PTR_ERROR;
|
return SLH_DSA_NULL_PTR_ERROR;
|
||||||
};
|
};
|
||||||
|
|
||||||
if message_buf.is_null() {return SLH_DSA_NULL_PTR_ERROR};
|
if message_buf.is_null() {
|
||||||
|
return SLH_DSA_NULL_PTR_ERROR;
|
||||||
|
};
|
||||||
|
|
||||||
let message = unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
let message =
|
||||||
|
unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
||||||
|
|
||||||
let Ok(sk) = fips205::slh_dsa_sha2_128f::PrivateKey::try_from_bytes(&private_key.data) else {
|
let Ok(sk) = fips205::slh_dsa_sha2_128f::PrivateKey::try_from_bytes(&private_key.data) else {
|
||||||
return SLH_DSA_DESERIALIZATION_ERROR;
|
return SLH_DSA_DESERIALIZATION_ERROR;
|
||||||
|
|
@ -83,22 +85,24 @@ pub extern "C" fn slh_dsa_sha2_128f_sign(
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn slh_dsa_sha2_128f_verify(
|
pub extern "C" fn slh_dsa_sha2_128f_verify(
|
||||||
message_buf: *const u8,
|
message_buf: *const u8, message_len: c_int,
|
||||||
message_len: c_int,
|
|
||||||
public_key: Option<&mut slh_dsa_sha2_128f_public_key>,
|
public_key: Option<&mut slh_dsa_sha2_128f_public_key>,
|
||||||
signature: Option<&mut slh_dsa_sha2_128f_signature>,
|
signature: Option<&mut slh_dsa_sha2_128f_signature>,
|
||||||
) -> u8 {
|
) -> u8 {
|
||||||
let (Some(public_key), Some(signature)) = (public_key, signature) else {
|
let (Some(public_key), Some(signature)) = (public_key, signature) else {
|
||||||
return SLH_DSA_NULL_PTR_ERROR;
|
return SLH_DSA_NULL_PTR_ERROR;
|
||||||
};
|
};
|
||||||
let message = unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
let message =
|
||||||
|
unsafe { std::slice::from_raw_parts(message_buf, message_len.try_into().unwrap()) };
|
||||||
|
|
||||||
let Ok(sk) = fips205::slh_dsa_sha2_128f::PublicKey::try_from_bytes(&public_key.data) else {
|
let Ok(sk) = fips205::slh_dsa_sha2_128f::PublicKey::try_from_bytes(&public_key.data) else {
|
||||||
return SLH_DSA_DESERIALIZATION_ERROR;
|
return SLH_DSA_DESERIALIZATION_ERROR;
|
||||||
};
|
};
|
||||||
let res = sk.try_verify_vt(&message, &signature.data);
|
let res = sk.try_verify_vt(&message, &signature.data);
|
||||||
|
|
||||||
if res.is_ok() && res.unwrap() { SLH_DSA_OK } else { SLH_DSA_VERIFY_ERROR }
|
if res.is_ok() && res.unwrap() {
|
||||||
|
SLH_DSA_OK
|
||||||
|
} else {
|
||||||
|
SLH_DSA_VERIFY_ERROR
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,12 +230,12 @@ impl Adrs {
|
||||||
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
|
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "slh_dsa_shake_128f",
|
feature = "slh_dsa_shake_128f",
|
||||||
feature = "slh_dsa_shake_128s",
|
feature = "slh_dsa_shake_128s",
|
||||||
feature = "slh_dsa_shake_192f",
|
feature = "slh_dsa_shake_192f",
|
||||||
feature = "slh_dsa_shake_192s",
|
feature = "slh_dsa_shake_192s",
|
||||||
feature = "slh_dsa_shake_256f",
|
feature = "slh_dsa_shake_256f",
|
||||||
feature = "slh_dsa_shake_256s"
|
feature = "slh_dsa_shake_256s"
|
||||||
))]
|
))]
|
||||||
pub(crate) fn to_32_bytes(&self) -> [u8; 32] {
|
pub(crate) fn to_32_bytes(&self) -> [u8; 32] {
|
||||||
let mut ret = [0u8; 32];
|
let mut ret = [0u8; 32];
|
||||||
|
|
@ -250,12 +250,12 @@ impl Adrs {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "slh_dsa_sha2_128f",
|
feature = "slh_dsa_sha2_128f",
|
||||||
feature = "slh_dsa_sha2_128s",
|
feature = "slh_dsa_sha2_128s",
|
||||||
feature = "slh_dsa_sha2_192f",
|
feature = "slh_dsa_sha2_192f",
|
||||||
feature = "slh_dsa_sha2_192s",
|
feature = "slh_dsa_sha2_192s",
|
||||||
feature = "slh_dsa_sha2_256f",
|
feature = "slh_dsa_sha2_256f",
|
||||||
feature = "slh_dsa_sha2_256s"
|
feature = "slh_dsa_sha2_256s"
|
||||||
))]
|
))]
|
||||||
pub(crate) fn to_22_bytes(&self) -> [u8; 22] {
|
pub(crate) fn to_22_bytes(&self) -> [u8; 22] {
|
||||||
let mut ret = [0u8; 22];
|
let mut ret = [0u8; 22];
|
||||||
|
|
|
||||||
|
|
@ -262,8 +262,8 @@ macro_rules! functionality {
|
||||||
fn simple_round_trips() {
|
fn simple_round_trips() {
|
||||||
let mut message = [0u8, 1, 2, 3];
|
let mut message = [0u8, 1, 2, 3];
|
||||||
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
|
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
|
||||||
for i in 0..5 {
|
for i in 0..5u8 {
|
||||||
message[3] = i as u8;
|
message[3] = i;
|
||||||
let (pk1, sk1) = KG::try_keygen_with_rng_vt(&mut rng).unwrap();
|
let (pk1, sk1) = KG::try_keygen_with_rng_vt(&mut rng).unwrap();
|
||||||
let pk1_bytes = pk1.into_bytes();
|
let pk1_bytes = pk1.into_bytes();
|
||||||
let pk2 = PublicKey::try_from_bytes(&pk1_bytes).unwrap();
|
let pk2 = PublicKey::try_from_bytes(&pk1_bytes).unwrap();
|
||||||
|
|
@ -272,7 +272,7 @@ macro_rules! functionality {
|
||||||
let sig = sk2.try_sign_with_rng_ct(&mut rng, &message, true).unwrap();
|
let sig = sk2.try_sign_with_rng_ct(&mut rng, &message, true).unwrap();
|
||||||
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
||||||
assert_eq!(result, true, "Signature failed to verify");
|
assert_eq!(result, true, "Signature failed to verify");
|
||||||
message[3] = (i + 1) as u8;
|
message[3] = (i + 1);
|
||||||
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
||||||
assert_eq!(result, false, "Signature should not have verified");
|
assert_eq!(result, false, "Signature should not have verified");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ pub struct XmssSig<const HP: usize, const LEN: usize, const N: usize> {
|
||||||
|
|
||||||
impl<const HP: usize, const LEN: usize, const N: usize> XmssSig<HP, LEN, N> {
|
impl<const HP: usize, const LEN: usize, const N: usize> XmssSig<HP, LEN, N> {
|
||||||
pub(crate) fn get_wots_sig(&self) -> &WotsSig<LEN, N> { &self.sig_wots }
|
pub(crate) fn get_wots_sig(&self) -> &WotsSig<LEN, N> { &self.sig_wots }
|
||||||
|
|
||||||
pub(crate) fn get_xmss_auth(&self) -> &[[u8; N]; HP] { &self.auth }
|
pub(crate) fn get_xmss_auth(&self) -> &[[u8; N]; HP] { &self.auth }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,435 +0,0 @@
|
||||||
/// Runs tests using data from exports posted by NIST in their ACVP-Server repository
|
|
||||||
/// ACVP: Automated Cryptographic Validation Protocol
|
|
||||||
///
|
|
||||||
/// Repo: https://github.com/usnistgov/ACVP-Server/
|
|
||||||
///
|
|
||||||
/// Test files:
|
|
||||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-keyGen-FIPS205/internalProjection.json
|
|
||||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigGen-FIPS205/internalProjection.json
|
|
||||||
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigVer-FIPS205/internalProjection.json
|
|
||||||
///
|
|
||||||
#[cfg(test)]
|
|
||||||
mod acvp_json_tests {
|
|
||||||
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
|
||||||
use rand_core::{CryptoRng, RngCore};
|
|
||||||
use serde::{Deserialize, Deserializer};
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::panic;
|
|
||||||
|
|
||||||
fn dehex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let buf = String::deserialize(deserializer)?;
|
|
||||||
hex::decode(buf).map_err(serde::de::Error::custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TestRng {
|
|
||||||
data: Vec<Vec<u8>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RngCore for TestRng {
|
|
||||||
fn next_u32(&mut self) -> u32 {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_u64(&mut self) -> u64 {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_bytes(&mut self, out: &mut [u8]) {
|
|
||||||
let x = self.data.pop().expect("TestRng problem");
|
|
||||||
out.copy_from_slice(&x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
|
|
||||||
self.fill_bytes(out);
|
|
||||||
Ok(()) // panic on probs is OK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CryptoRng for TestRng {}
|
|
||||||
|
|
||||||
impl TestRng {
|
|
||||||
fn new() -> Self {
|
|
||||||
TestRng { data: Vec::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(&mut self, new_data: &[u8]) {
|
|
||||||
let x = new_data.to_vec();
|
|
||||||
self.data.push(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct KeyGenTest {
|
|
||||||
tc_id: usize,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
sk_seed: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
sk_prf: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
pk_seed: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
sk: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
pk: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test_keygen {
|
|
||||||
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
|
||||||
for test in $test_group["tests"].as_array().unwrap() {
|
|
||||||
let test: KeyGenTest = serde_json::from_value(test.clone()).unwrap();
|
|
||||||
print!(
|
|
||||||
"Testing key generation with {} test case id {}... ",
|
|
||||||
$param_set, test.tc_id
|
|
||||||
);
|
|
||||||
|
|
||||||
// Pre-load RNG
|
|
||||||
let mut rnd = TestRng::new();
|
|
||||||
rnd.push(&test.pk_seed);
|
|
||||||
rnd.push(&test.sk_prf);
|
|
||||||
rnd.push(&test.sk_seed);
|
|
||||||
|
|
||||||
// Generate key
|
|
||||||
let (pk, sk) = KG::try_keygen_with_rng_vt(&mut rnd).unwrap();
|
|
||||||
|
|
||||||
// Check against known answers
|
|
||||||
let pk_match = pk.into_bytes() == test.pk.as_slice();
|
|
||||||
let sk_match = sk.into_bytes() == test.sk.as_slice();
|
|
||||||
if pk_match && sk_match {
|
|
||||||
println!("Passed.")
|
|
||||||
} else {
|
|
||||||
println!("Failed.");
|
|
||||||
$fail_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn run_keygen_tests() {
|
|
||||||
let mut fail_count = 0;
|
|
||||||
let file = "tests/SLH-DSA-keyGen-FIPS205/internalProjection.json";
|
|
||||||
let keygen_kat_file = File::open(file).expect("Error opening json file");
|
|
||||||
let kat_json: Value =
|
|
||||||
serde_json::from_reader(keygen_kat_file).expect("Error parsing json file");
|
|
||||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
|
||||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "keyGen");
|
|
||||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
|
||||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
|
||||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
|
||||||
match param_set {
|
|
||||||
"SLH-DSA-SHA2-128s" => {
|
|
||||||
use fips205::slh_dsa_sha2_128s::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-128s" => {
|
|
||||||
use fips205::slh_dsa_shake_128s::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-128f" => {
|
|
||||||
use fips205::slh_dsa_sha2_128f::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-128f" => {
|
|
||||||
use fips205::slh_dsa_shake_128f::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-192s" => {
|
|
||||||
use fips205::slh_dsa_sha2_192s::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-192s" => {
|
|
||||||
use fips205::slh_dsa_shake_192s::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-192f" => {
|
|
||||||
use fips205::slh_dsa_sha2_192f::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-192f" => {
|
|
||||||
use fips205::slh_dsa_shake_192f::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-256s" => {
|
|
||||||
use fips205::slh_dsa_sha2_256s::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-256s" => {
|
|
||||||
use fips205::slh_dsa_shake_256s::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-256f" => {
|
|
||||||
use fips205::slh_dsa_sha2_256f::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-256f" => {
|
|
||||||
use fips205::slh_dsa_shake_256f::KG;
|
|
||||||
test_keygen!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_eq!(fail_count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct SignTest {
|
|
||||||
tc_id: usize,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
sk: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex", default)]
|
|
||||||
additional_randomness: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
message: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
signature: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test_sign {
|
|
||||||
($test_group: ident, $param_set: ident, $deterministic:ident, $fail_count: ident) => {
|
|
||||||
for test in $test_group["tests"].as_array().unwrap() {
|
|
||||||
let test: SignTest = serde_json::from_value(test.clone()).unwrap();
|
|
||||||
print!("Testing signing with {}, test case {}... ", $param_set, test.tc_id);
|
|
||||||
|
|
||||||
// Load private key
|
|
||||||
let sk = PrivateKey::try_from_bytes(
|
|
||||||
test.sk
|
|
||||||
.as_slice()
|
|
||||||
.try_into()
|
|
||||||
.expect("Wrong length private key"),
|
|
||||||
)
|
|
||||||
.expect("Unable to load private key");
|
|
||||||
|
|
||||||
// Calculate signature
|
|
||||||
let sig_exp = if $deterministic {
|
|
||||||
sk.try_sign_ct(&test.message, false)
|
|
||||||
.expect("Error signing message")
|
|
||||||
} else {
|
|
||||||
let mut rnd = TestRng::new();
|
|
||||||
rnd.push(test.additional_randomness.as_slice());
|
|
||||||
sk.try_sign_with_rng_ct(&mut rnd, &test.message, true)
|
|
||||||
.expect("Error signing message")
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check against known answer
|
|
||||||
if sig_exp == test.signature.as_slice() {
|
|
||||||
println!("Passed.");
|
|
||||||
} else {
|
|
||||||
println!("Failed.");
|
|
||||||
$fail_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn run_signing_tests() {
|
|
||||||
let mut fail_count = 0;
|
|
||||||
let file = "tests/SLH-DSA-sigGen-FIPS205/internalProjection.json";
|
|
||||||
let sign_kat_file = File::open(file).expect("Error opening json file");
|
|
||||||
let kat_json: Value =
|
|
||||||
serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
|
||||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
|
||||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigGen");
|
|
||||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
|
||||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
|
||||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
|
||||||
let deterministic = test_group["deterministic"].as_bool().unwrap();
|
|
||||||
match param_set {
|
|
||||||
"SLH-DSA-SHA2-128s" => {
|
|
||||||
use fips205::slh_dsa_sha2_128s::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-128s" => {
|
|
||||||
use fips205::slh_dsa_shake_128s::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-128f" => {
|
|
||||||
use fips205::slh_dsa_sha2_128f::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-128f" => {
|
|
||||||
use fips205::slh_dsa_shake_128f::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-192s" => {
|
|
||||||
use fips205::slh_dsa_sha2_192s::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-192s" => {
|
|
||||||
use fips205::slh_dsa_shake_192s::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-192f" => {
|
|
||||||
use fips205::slh_dsa_sha2_192f::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-192f" => {
|
|
||||||
use fips205::slh_dsa_shake_192f::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-256s" => {
|
|
||||||
use fips205::slh_dsa_sha2_256s::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-256s" => {
|
|
||||||
use fips205::slh_dsa_shake_256s::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-256f" => {
|
|
||||||
use fips205::slh_dsa_sha2_256f::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-256f" => {
|
|
||||||
use fips205::slh_dsa_shake_256f::PrivateKey;
|
|
||||||
test_sign!(test_group, param_set, deterministic, fail_count);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_eq!(fail_count, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
struct VerifyTest {
|
|
||||||
tc_id: usize,
|
|
||||||
test_passed: bool,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
pk: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
message: Vec<u8>,
|
|
||||||
#[serde(deserialize_with = "dehex")]
|
|
||||||
signature: Vec<u8>,
|
|
||||||
reason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test_verify {
|
|
||||||
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
|
||||||
for test in $test_group["tests"].as_array().unwrap() {
|
|
||||||
let test: VerifyTest = serde_json::from_value(test.clone()).unwrap();
|
|
||||||
print!(
|
|
||||||
"Testing signing with {}, test case {}... ",
|
|
||||||
$param_set,
|
|
||||||
test.tc_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
if test.test_passed == false {
|
|
||||||
println!("\nExpecting failed validation for: {}", test.reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_valid: Result<bool, _> = panic::catch_unwind(|| {
|
|
||||||
// Load public key
|
|
||||||
let pk = PublicKey::try_from_bytes(
|
|
||||||
test.pk
|
|
||||||
.as_slice()
|
|
||||||
.try_into()
|
|
||||||
.expect("Wrong length public key"),
|
|
||||||
)
|
|
||||||
.expect("Unable to load public key");
|
|
||||||
|
|
||||||
// Verify signature
|
|
||||||
pk.try_verify_vt(
|
|
||||||
test.message.as_slice(),
|
|
||||||
test.signature
|
|
||||||
.as_slice()
|
|
||||||
.try_into()
|
|
||||||
.expect("Signature length incorrect"),
|
|
||||||
)
|
|
||||||
.expect("Verification failed")
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check against known answer
|
|
||||||
let is_valid = match is_valid {
|
|
||||||
Ok(true) => true,
|
|
||||||
Ok(false) => false,
|
|
||||||
Err(_) => false,
|
|
||||||
};
|
|
||||||
if is_valid == test.test_passed {
|
|
||||||
println!("Passed.");
|
|
||||||
} else {
|
|
||||||
println!("Failed.");
|
|
||||||
$fail_count += 1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn run_verification_tests() {
|
|
||||||
let mut fail_count = 0;
|
|
||||||
let file = "tests/SLH-DSA-sigVer-FIPS205/internalProjection.json";
|
|
||||||
let sign_kat_file = File::open(file).expect("Error opening json file");
|
|
||||||
let kat_json: Value =
|
|
||||||
serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
|
||||||
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
|
||||||
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigVer");
|
|
||||||
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
|
||||||
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
|
||||||
let param_set = test_group["parameterSet"].as_str().unwrap();
|
|
||||||
match param_set {
|
|
||||||
"SLH-DSA-SHA2-128s" => {
|
|
||||||
use fips205::slh_dsa_sha2_128s::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-128s" => {
|
|
||||||
use fips205::slh_dsa_shake_128s::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-128f" => {
|
|
||||||
use fips205::slh_dsa_sha2_128f::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-128f" => {
|
|
||||||
use fips205::slh_dsa_shake_128f::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-192s" => {
|
|
||||||
use fips205::slh_dsa_sha2_192s::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-192s" => {
|
|
||||||
use fips205::slh_dsa_shake_192s::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-192f" => {
|
|
||||||
use fips205::slh_dsa_sha2_192f::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-192f" => {
|
|
||||||
use fips205::slh_dsa_shake_192f::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-256s" => {
|
|
||||||
use fips205::slh_dsa_sha2_256s::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-256s" => {
|
|
||||||
use fips205::slh_dsa_shake_256s::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHA2-256f" => {
|
|
||||||
use fips205::slh_dsa_sha2_256f::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
"SLH-DSA-SHAKE-256f" => {
|
|
||||||
use fips205::slh_dsa_shake_256f::PublicKey;
|
|
||||||
test_verify!(test_group, param_set, fail_count);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("Unrecognized Parameter set in test file: {}", param_set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_eq!(fail_count, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
tests/integration.rs
Normal file
1
tests/integration.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
mod nist_acvp_vectors;
|
||||||
File diff suppressed because one or more lines are too long
416
tests/nist_acvp_vectors/mod.rs
Normal file
416
tests/nist_acvp_vectors/mod.rs
Normal file
|
|
@ -0,0 +1,416 @@
|
||||||
|
/// Runs tests using data from exports posted by NIST in their ACVP-Server repository
|
||||||
|
/// ACVP: Automated Cryptographic Validation Protocol
|
||||||
|
///
|
||||||
|
/// Repo: https://github.com/usnistgov/ACVP-Server/
|
||||||
|
///
|
||||||
|
/// Test files:
|
||||||
|
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-keyGen-FIPS205/internalProjection.json
|
||||||
|
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigGen-FIPS205/internalProjection.json
|
||||||
|
/// - https://github.com/usnistgov/ACVP-Server/raw/master/gen-val/json-files/SLH-DSA-sigVer-FIPS205/internalProjection.json
|
||||||
|
use fips205::traits::{KeyGen, SerDes, Signer, Verifier};
|
||||||
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
use serde_json::Value;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::panic;
|
||||||
|
|
||||||
|
fn dehex<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let buf = String::deserialize(deserializer)?;
|
||||||
|
hex::decode(buf).map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestRng {
|
||||||
|
data: Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RngCore for TestRng {
|
||||||
|
fn next_u32(&mut self) -> u32 { unimplemented!() }
|
||||||
|
|
||||||
|
fn next_u64(&mut self) -> u64 { unimplemented!() }
|
||||||
|
|
||||||
|
fn fill_bytes(&mut self, out: &mut [u8]) {
|
||||||
|
let x = self.data.pop().expect("TestRng problem");
|
||||||
|
out.copy_from_slice(&x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
|
||||||
|
self.fill_bytes(out);
|
||||||
|
Ok(()) // panic on probs is OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CryptoRng for TestRng {}
|
||||||
|
|
||||||
|
impl TestRng {
|
||||||
|
fn new() -> Self { TestRng { data: Vec::new() } }
|
||||||
|
|
||||||
|
fn push(&mut self, new_data: &[u8]) {
|
||||||
|
let x = new_data.to_vec();
|
||||||
|
self.data.push(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct KeyGenTest {
|
||||||
|
tc_id: usize,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
sk_seed: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
sk_prf: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
pk_seed: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
sk: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
pk: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_keygen {
|
||||||
|
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
||||||
|
for test in $test_group["tests"].as_array().unwrap() {
|
||||||
|
let test: KeyGenTest = serde_json::from_value(test.clone()).unwrap();
|
||||||
|
print!("Testing key generation with {} test case id {}... ", $param_set, test.tc_id);
|
||||||
|
|
||||||
|
// Pre-load RNG
|
||||||
|
let mut rnd = TestRng::new();
|
||||||
|
rnd.push(&test.pk_seed);
|
||||||
|
rnd.push(&test.sk_prf);
|
||||||
|
rnd.push(&test.sk_seed);
|
||||||
|
|
||||||
|
// Generate key
|
||||||
|
let (pk, sk) = KG::try_keygen_with_rng_vt(&mut rnd).unwrap();
|
||||||
|
|
||||||
|
// Check against known answers
|
||||||
|
let pk_match = pk.into_bytes() == test.pk.as_slice();
|
||||||
|
let sk_match = sk.into_bytes() == test.sk.as_slice();
|
||||||
|
if pk_match && sk_match {
|
||||||
|
println!("Passed.")
|
||||||
|
} else {
|
||||||
|
println!("Failed.");
|
||||||
|
$fail_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn run_keygen_tests() {
|
||||||
|
let mut fail_count = 0;
|
||||||
|
let file = "tests/nist_acvp_vectors/SLH-DSA-keyGen-FIPS205/internalProjection.json";
|
||||||
|
let keygen_kat_file = File::open(file).expect("Error opening json file");
|
||||||
|
let kat_json: Value =
|
||||||
|
serde_json::from_reader(keygen_kat_file).expect("Error parsing json file");
|
||||||
|
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||||
|
assert_eq!(kat_json["mode"].as_str().unwrap(), "keyGen");
|
||||||
|
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||||
|
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||||
|
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||||
|
match param_set {
|
||||||
|
"SLH-DSA-SHA2-128s" => {
|
||||||
|
use fips205::slh_dsa_sha2_128s::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-128s" => {
|
||||||
|
use fips205::slh_dsa_shake_128s::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-128f" => {
|
||||||
|
use fips205::slh_dsa_sha2_128f::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-128f" => {
|
||||||
|
use fips205::slh_dsa_shake_128f::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-192s" => {
|
||||||
|
use fips205::slh_dsa_sha2_192s::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-192s" => {
|
||||||
|
use fips205::slh_dsa_shake_192s::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-192f" => {
|
||||||
|
use fips205::slh_dsa_sha2_192f::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-192f" => {
|
||||||
|
use fips205::slh_dsa_shake_192f::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-256s" => {
|
||||||
|
use fips205::slh_dsa_sha2_256s::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-256s" => {
|
||||||
|
use fips205::slh_dsa_shake_256s::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-256f" => {
|
||||||
|
use fips205::slh_dsa_sha2_256f::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-256f" => {
|
||||||
|
use fips205::slh_dsa_shake_256f::KG;
|
||||||
|
test_keygen!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(fail_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct SignTest {
|
||||||
|
tc_id: usize,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
sk: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex", default)]
|
||||||
|
additional_randomness: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
message: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
signature: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_sign {
|
||||||
|
($test_group: ident, $param_set: ident, $deterministic:ident, $fail_count: ident) => {
|
||||||
|
for test in $test_group["tests"].as_array().unwrap() {
|
||||||
|
let test: SignTest = serde_json::from_value(test.clone()).unwrap();
|
||||||
|
print!("Testing signing with {}, test case {}... ", $param_set, test.tc_id);
|
||||||
|
|
||||||
|
// Load private key
|
||||||
|
let sk = PrivateKey::try_from_bytes(
|
||||||
|
test.sk
|
||||||
|
.as_slice()
|
||||||
|
.try_into()
|
||||||
|
.expect("Wrong length private key"),
|
||||||
|
)
|
||||||
|
.expect("Unable to load private key");
|
||||||
|
|
||||||
|
// Calculate signature
|
||||||
|
let sig_exp = if $deterministic {
|
||||||
|
sk.try_sign_ct(&test.message, false)
|
||||||
|
.expect("Error signing message")
|
||||||
|
} else {
|
||||||
|
let mut rnd = TestRng::new();
|
||||||
|
rnd.push(test.additional_randomness.as_slice());
|
||||||
|
sk.try_sign_with_rng_ct(&mut rnd, &test.message, true)
|
||||||
|
.expect("Error signing message")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check against known answer
|
||||||
|
if sig_exp == test.signature.as_slice() {
|
||||||
|
println!("Passed.");
|
||||||
|
} else {
|
||||||
|
println!("Failed.");
|
||||||
|
$fail_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn run_signing_tests() {
|
||||||
|
let mut fail_count = 0;
|
||||||
|
let file = "tests/nist_acvp_vectors/SLH-DSA-sigGen-FIPS205/internalProjection.json";
|
||||||
|
let sign_kat_file = File::open(file).expect("Error opening json file");
|
||||||
|
let kat_json: Value = serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
||||||
|
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||||
|
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigGen");
|
||||||
|
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||||
|
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||||
|
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||||
|
let deterministic = test_group["deterministic"].as_bool().unwrap();
|
||||||
|
match param_set {
|
||||||
|
"SLH-DSA-SHA2-128s" => {
|
||||||
|
use fips205::slh_dsa_sha2_128s::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-128s" => {
|
||||||
|
use fips205::slh_dsa_shake_128s::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-128f" => {
|
||||||
|
use fips205::slh_dsa_sha2_128f::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-128f" => {
|
||||||
|
use fips205::slh_dsa_shake_128f::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-192s" => {
|
||||||
|
use fips205::slh_dsa_sha2_192s::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-192s" => {
|
||||||
|
use fips205::slh_dsa_shake_192s::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-192f" => {
|
||||||
|
use fips205::slh_dsa_sha2_192f::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-192f" => {
|
||||||
|
use fips205::slh_dsa_shake_192f::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-256s" => {
|
||||||
|
use fips205::slh_dsa_sha2_256s::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-256s" => {
|
||||||
|
use fips205::slh_dsa_shake_256s::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-256f" => {
|
||||||
|
use fips205::slh_dsa_sha2_256f::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-256f" => {
|
||||||
|
use fips205::slh_dsa_shake_256f::PrivateKey;
|
||||||
|
test_sign!(test_group, param_set, deterministic, fail_count);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(fail_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct VerifyTest {
|
||||||
|
tc_id: usize,
|
||||||
|
test_passed: bool,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
pk: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
message: Vec<u8>,
|
||||||
|
#[serde(deserialize_with = "dehex")]
|
||||||
|
signature: Vec<u8>,
|
||||||
|
reason: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_verify {
|
||||||
|
($test_group: ident, $param_set: ident, $fail_count: ident) => {
|
||||||
|
for test in $test_group["tests"].as_array().unwrap() {
|
||||||
|
let test: VerifyTest = serde_json::from_value(test.clone()).unwrap();
|
||||||
|
print!("Testing signing with {}, test case {}... ", $param_set, test.tc_id,);
|
||||||
|
|
||||||
|
if test.test_passed == false {
|
||||||
|
println!("\nExpecting failed validation for: {}", test.reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_valid: Result<bool, _> = panic::catch_unwind(|| {
|
||||||
|
// Load public key
|
||||||
|
let pk = PublicKey::try_from_bytes(
|
||||||
|
test.pk
|
||||||
|
.as_slice()
|
||||||
|
.try_into()
|
||||||
|
.expect("Wrong length public key"),
|
||||||
|
)
|
||||||
|
.expect("Unable to load public key");
|
||||||
|
|
||||||
|
// Verify signature
|
||||||
|
pk.try_verify_vt(
|
||||||
|
test.message.as_slice(),
|
||||||
|
test.signature
|
||||||
|
.as_slice()
|
||||||
|
.try_into()
|
||||||
|
.expect("Signature length incorrect"),
|
||||||
|
)
|
||||||
|
.expect("Verification failed")
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check against known answer
|
||||||
|
let is_valid = match is_valid {
|
||||||
|
Ok(true) => true,
|
||||||
|
Ok(false) => false,
|
||||||
|
Err(_) => false,
|
||||||
|
};
|
||||||
|
if is_valid == test.test_passed {
|
||||||
|
println!("Passed.");
|
||||||
|
} else {
|
||||||
|
println!("Failed.");
|
||||||
|
$fail_count += 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn run_verification_tests() {
|
||||||
|
let mut fail_count = 0;
|
||||||
|
let file = "tests/nist_acvp_vectors/SLH-DSA-sigVer-FIPS205/internalProjection.json";
|
||||||
|
let sign_kat_file = File::open(file).expect("Error opening json file");
|
||||||
|
let kat_json: Value = serde_json::from_reader(sign_kat_file).expect("Error parsing json file");
|
||||||
|
assert_eq!(kat_json["algorithm"].as_str().unwrap(), "SLH-DSA");
|
||||||
|
assert_eq!(kat_json["mode"].as_str().unwrap(), "sigVer");
|
||||||
|
assert_eq!(kat_json["revision"].as_str().unwrap(), "FIPS205");
|
||||||
|
for test_group in kat_json["testGroups"].as_array().unwrap() {
|
||||||
|
let param_set = test_group["parameterSet"].as_str().unwrap();
|
||||||
|
match param_set {
|
||||||
|
"SLH-DSA-SHA2-128s" => {
|
||||||
|
use fips205::slh_dsa_sha2_128s::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-128s" => {
|
||||||
|
use fips205::slh_dsa_shake_128s::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-128f" => {
|
||||||
|
use fips205::slh_dsa_sha2_128f::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-128f" => {
|
||||||
|
use fips205::slh_dsa_shake_128f::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-192s" => {
|
||||||
|
use fips205::slh_dsa_sha2_192s::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-192s" => {
|
||||||
|
use fips205::slh_dsa_shake_192s::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-192f" => {
|
||||||
|
use fips205::slh_dsa_sha2_192f::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-192f" => {
|
||||||
|
use fips205::slh_dsa_shake_192f::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-256s" => {
|
||||||
|
use fips205::slh_dsa_sha2_256s::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-256s" => {
|
||||||
|
use fips205::slh_dsa_shake_256s::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHA2-256f" => {
|
||||||
|
use fips205::slh_dsa_sha2_256f::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
"SLH-DSA-SHAKE-256f" => {
|
||||||
|
use fips205::slh_dsa_shake_256f::PublicKey;
|
||||||
|
test_verify!(test_group, param_set, fail_count);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("Unrecognized Parameter set in test file: {}", param_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(fail_count, 0);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue