mirror of
https://github.com/henrydcase/pqc.git
synced 2024-11-22 15:39:07 +00:00
[cavptool] update
This commit is contained in:
parent
b01ea397e2
commit
01be5610c1
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@ -83,9 +83,9 @@ jobs:
|
|||||||
- name: Run KAT tests
|
- name: Run KAT tests
|
||||||
run: |
|
run: |
|
||||||
cd test/katrunner &&
|
cd test/katrunner &&
|
||||||
curl http://amongbytes.com/~flowher/permalinks/kat.zip --output kat.zip
|
curl http://nice.pqsh.net/files/kat.zip --output kat.zip
|
||||||
unzip kat.zip
|
unzip kat.zip
|
||||||
cargo run --release -- --katdir KAT
|
cargo run --release -- --katdir kat
|
||||||
MEMSAN:
|
MEMSAN:
|
||||||
name: Memory Sanitizer build
|
name: Memory Sanitizer build
|
||||||
runs-on: [ubuntu-20.04]
|
runs-on: [ubuntu-20.04]
|
||||||
|
@ -14,7 +14,7 @@ extern "C" {
|
|||||||
#include "kem/kyber/kyber512/avx2/ntt.h"
|
#include "kem/kyber/kyber512/avx2/ntt.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cpucycle = [](benchmark::State &st, int64_t cycles) {
|
static auto cpucycle = [](benchmark::State &st, int64_t cycles) {
|
||||||
st.counters["CPU cycles: mean"] = benchmark::Counter(
|
st.counters["CPU cycles: mean"] = benchmark::Counter(
|
||||||
cycles, benchmark::Counter::kAvgIterations | benchmark::Counter::kResultNoFormat);
|
cycles, benchmark::Counter::kAvgIterations | benchmark::Counter::kResultNoFormat);
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#define ARRAY_LEN(X) sizeof(X)/sizeof(X[0])
|
#define ARRAY_LEN(X) sizeof(X)/sizeof(X[0])
|
||||||
|
|
||||||
|
|
||||||
auto cpucycle = [](benchmark::State &st, int64_t cycles) {
|
static auto cpucycle = [](benchmark::State &st, int64_t cycles) {
|
||||||
st.counters["CPU cycles: mean"] = benchmark::Counter(
|
st.counters["CPU cycles: mean"] = benchmark::Counter(
|
||||||
cycles, benchmark::Counter::kAvgIterations | benchmark::Counter::kResultNoFormat);
|
cycles, benchmark::Counter::kAvgIterations | benchmark::Counter::kResultNoFormat);
|
||||||
};
|
};
|
||||||
|
@ -5,12 +5,20 @@ use std::env;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use threadpool::ThreadPool;
|
use threadpool::ThreadPool;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use aes_ctr_drbg::DrbgCtx;
|
use aes_ctr_drbg::DrbgCtx as AesCtrDrbgCtx;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum TestStatus {
|
||||||
|
Processed,
|
||||||
|
// For now this variant is not used
|
||||||
|
#[allow(dead_code)]
|
||||||
|
Skipped,
|
||||||
|
}
|
||||||
|
|
||||||
// Used for signature algorithm registration
|
// Used for signature algorithm registration
|
||||||
macro_rules! REG_SIGN {
|
macro_rules! REG_SIGN {
|
||||||
($ID:expr,$F:expr) => {
|
($ID:expr,$F:expr) => {
|
||||||
@ -33,13 +41,88 @@ macro_rules! REG_KEM {
|
|||||||
execfn: test_kem_vector}
|
execfn: test_kem_vector}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Needed to implement get_rng.
|
||||||
|
trait Rng {
|
||||||
|
fn init(&mut self, entropy: &[u8], diversifier: Vec<u8>);
|
||||||
|
fn get_random(&mut self, data: &mut [u8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DummyDrbg just returns value of self.data. Useful
|
||||||
|
// in testing functions that are non-deterministic.
|
||||||
|
struct DummyDrbgContext{
|
||||||
|
data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rng for DummyDrbgContext {
|
||||||
|
fn init(&mut self, entropy: &[u8], _diversifier: Vec<u8>) {
|
||||||
|
self.data = entropy.to_vec();
|
||||||
|
}
|
||||||
|
fn get_random(&mut self, data: &mut [u8]) {
|
||||||
|
for i in 0..std::cmp::min(data.len(), self.data.len()) {
|
||||||
|
data[i] = self.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrbgCtx uses AES-CTR to generate random byte-string.
|
||||||
|
impl Rng for AesCtrDrbgCtx {
|
||||||
|
fn init(&mut self, entropy: &[u8], diversifier: Vec<u8>) {
|
||||||
|
self.init(entropy, diversifier);
|
||||||
|
}
|
||||||
|
fn get_random(&mut self, data: &mut [u8]) {
|
||||||
|
self.get_random(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allows to use some custom Drbg that implements
|
||||||
|
// Rng trait. In Current implementation if `use_aes`
|
||||||
|
// is set then AesCtrDrbgCtx is used (default), otherwise
|
||||||
|
// DummyDrbg is used.
|
||||||
|
struct CustomizableDrbgCtx{
|
||||||
|
aes_drbg: AesCtrDrbgCtx,
|
||||||
|
dummy: DummyDrbgContext,
|
||||||
|
use_aes: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CustomizableDrbgCtx{
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
use_aes: true,
|
||||||
|
aes_drbg: AesCtrDrbgCtx::new(),
|
||||||
|
dummy: DummyDrbgContext{
|
||||||
|
data: Vec::new(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: possibily to be done with Box<> or something
|
||||||
|
fn get_rng(&mut self) -> &mut dyn Rng {
|
||||||
|
if self.use_aes {
|
||||||
|
return &mut self.aes_drbg;
|
||||||
|
} else {
|
||||||
|
return &mut self.dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(&mut self, entropy: &[u8], diversifier: Vec<u8>, is_fixed: bool) {
|
||||||
|
if is_fixed {
|
||||||
|
self.use_aes = false;
|
||||||
|
}
|
||||||
|
self.get_rng().init(entropy, diversifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_random(&mut self, data: &mut [u8]) {
|
||||||
|
self.get_rng().get_random(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stores one DRBG context per execution thread. DRBG
|
// Stores one DRBG context per execution thread. DRBG
|
||||||
// is inserted in this map, just after thread starts
|
// is inserted in this map, just after thread starts
|
||||||
// and removed after thread is finished. Operation
|
// and removed after thread is finished. Operation
|
||||||
// is synchronized.
|
// is synchronized.
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref DRBGV: Mutex<HashMap<thread::ThreadId, DrbgCtx>> = Mutex::new(HashMap::new());
|
static ref DRBGV: Mutex<
|
||||||
|
HashMap<thread::ThreadId, CustomizableDrbgCtx>> = Mutex::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to provide the implementation for randombytes
|
// We have to provide the implementation for randombytes
|
||||||
@ -53,22 +136,21 @@ unsafe extern "C" fn randombytes(
|
|||||||
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
||||||
drbg.get_random(&mut slice);
|
drbg.get_random(&mut slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExecFn = fn(&TestVector);
|
type ExecFn = fn(&TestVector) -> TestStatus;
|
||||||
struct Register {
|
struct Register {
|
||||||
kat: katwalk::reader::Kat,
|
kat: katwalk::reader::Kat,
|
||||||
execfn: ExecFn,
|
execfn: ExecFn,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_sign_vector(el: &TestVector) {
|
fn test_sign_vector(el: &TestVector) -> TestStatus {
|
||||||
let mut pk = Vec::new();
|
let mut pk = Vec::new();
|
||||||
let mut sk = Vec::new();
|
let mut sk = Vec::new();
|
||||||
let mut sm = Vec::new();
|
let mut sm = Vec::new();
|
||||||
|
|
||||||
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
||||||
drbg.init(el.sig.seed.as_slice(), Vec::new());
|
drbg.init(el.sig.seed.as_slice(), Vec::new(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -114,17 +196,18 @@ fn test_sign_vector(el: &TestVector) {
|
|||||||
el.sig.msg.as_ptr(), el.sig.msg.len() as u64,
|
el.sig.msg.as_ptr(), el.sig.msg.len() as u64,
|
||||||
el.sig.pk.as_ptr()),
|
el.sig.pk.as_ptr()),
|
||||||
true);
|
true);
|
||||||
|
return TestStatus::Processed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_kem_vector(el: &TestVector) {
|
fn test_kem_vector(el: &TestVector) -> TestStatus {
|
||||||
let mut pk = Vec::new();
|
let mut pk = Vec::new();
|
||||||
let mut sk = Vec::new();
|
let mut sk = Vec::new();
|
||||||
let mut ct = Vec::new();
|
let mut ct = Vec::new();
|
||||||
let mut ss = Vec::new();
|
let mut ss = Vec::new();
|
||||||
|
|
||||||
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
||||||
drbg.init(el.kem.seed.as_slice(), Vec::new());
|
drbg.init(el.kem.seed.as_slice(), Vec::new(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -161,6 +244,7 @@ fn test_kem_vector(el: &TestVector) {
|
|||||||
true);
|
true);
|
||||||
assert_eq!(ss, el.kem.ss);
|
assert_eq!(ss, el.kem.ss);
|
||||||
}
|
}
|
||||||
|
return TestStatus::Processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// KAT test register
|
// KAT test register
|
||||||
@ -221,30 +305,50 @@ const KATS: &'static[Register] = &[
|
|||||||
REG_KEM!(PQC_ALG_KEM_SIKE434, "round3/sike/PQCkemKAT_374.rsp"),
|
REG_KEM!(PQC_ALG_KEM_SIKE434, "round3/sike/PQCkemKAT_374.rsp"),
|
||||||
];
|
];
|
||||||
|
|
||||||
fn execute(kat_dir: String, thc: usize, file_filter: &str) {
|
// Main loop
|
||||||
|
fn execute(kat_dir: String, thc: usize, file_filter: &str) -> u8 {
|
||||||
// Can't do multi-threads as DRBG context is global
|
// Can't do multi-threads as DRBG context is global
|
||||||
let pool = ThreadPool::new(thc);
|
let pool = ThreadPool::new(thc);
|
||||||
|
let path = Path::new(&kat_dir);
|
||||||
|
let mut code: u8 = 0;
|
||||||
|
|
||||||
for k in KATS.iter() {
|
for k in KATS.iter() {
|
||||||
let tmp = kat_dir.clone();
|
|
||||||
if !file_filter.is_empty() && !k.kat.kat_file.contains(file_filter) {
|
if !file_filter.is_empty() && !k.kat.kat_file.contains(file_filter) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
let filepath = path.join(k.kat.kat_file);
|
||||||
|
let fhandle = match File::open(filepath) {
|
||||||
|
Ok(fhandle) => fhandle,
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("File {:?} doesn't exist", k.kat.kat_file);
|
||||||
|
code |= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let buf = BufReader::new(fhandle);
|
||||||
|
|
||||||
pool.execute(move || {
|
pool.execute(move || {
|
||||||
DRBGV.lock().unwrap()
|
DRBGV.lock().unwrap()
|
||||||
.insert(thread::current().id(), DrbgCtx::new());
|
.insert(thread::current().id(), CustomizableDrbgCtx::new());
|
||||||
let f = Path::new(&tmp.to_string()).join(k.kat.kat_file);
|
let proc = KatReader::new(buf, k.kat.scheme_type, k.kat.scheme_id);
|
||||||
let file = File::open(format!("{}", f.to_str().unwrap()));
|
let iter = proc.into_iter();
|
||||||
println!("Processing file: {}", Path::new(k.kat.kat_file).to_str().unwrap());
|
let mut processed = 0;
|
||||||
let b = BufReader::new(file.unwrap());
|
let mut skipped = 0;
|
||||||
|
for el in iter {
|
||||||
for el in KatReader::new(b, k.kat.scheme_type, k.kat.scheme_id) {
|
let status = (k.execfn)(&el);
|
||||||
(k.execfn)(&el);
|
match status {
|
||||||
|
TestStatus::Processed => processed += 1,
|
||||||
|
TestStatus::Skipped => skipped += 1,
|
||||||
}
|
}
|
||||||
DRBGV.lock().unwrap()
|
}
|
||||||
.remove(&thread::current().id());
|
println!("{:60} KAT# : {:10}{:10}", k.kat.kat_file, processed,skipped);
|
||||||
|
DRBGV.lock().unwrap().remove(&thread::current().id());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pool.join();
|
pool.join();
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -259,6 +363,7 @@ fn main() {
|
|||||||
argmap.insert(&args[i], &args[i+1]);
|
argmap.insert(&args[i], &args[i+1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Number of threads to be used
|
||||||
let thread_number: usize = match argmap.get(&"--threads".to_string()) {
|
let thread_number: usize = match argmap.get(&"--threads".to_string()) {
|
||||||
Some(n) => n.to_string().parse::<usize>().unwrap(),
|
Some(n) => n.to_string().parse::<usize>().unwrap(),
|
||||||
None => 4 /* by default 4 threads */,
|
None => 4 /* by default 4 threads */,
|
||||||
@ -270,8 +375,13 @@ fn main() {
|
|||||||
None => ""
|
None => ""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Header for the results
|
||||||
|
println!("Test file{:60}Processed Skipped", "");
|
||||||
|
println!("------------------------------------------------------------------------------------------");
|
||||||
match argmap.get(&"--katdir".to_string()) {
|
match argmap.get(&"--katdir".to_string()) {
|
||||||
Some(kat_dir) => execute(kat_dir.to_string(), thread_number, file_filter),
|
Some(kat_dir) =>
|
||||||
|
std::process::exit(
|
||||||
|
execute(kat_dir.to_string(), thread_number, file_filter).into()),
|
||||||
None => panic!("--katdir required")
|
None => panic!("--katdir required")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user