дзеркало
https://github.com/henrydcase/pqc.git
synced 2024-11-25 17:01:22 +00:00
[cavptool] update
This commit is contained in:
джерело
b01ea397e2
коміт
18a0140f44
4
.github/workflows/main.yml
сторонній
4
.github/workflows/main.yml
сторонній
@ -83,9 +83,9 @@ jobs:
|
||||
- name: Run KAT tests
|
||||
run: |
|
||||
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
|
||||
cargo run --release -- --katdir KAT
|
||||
cargo run --release -- --katdir kat
|
||||
MEMSAN:
|
||||
name: Memory Sanitizer build
|
||||
runs-on: [ubuntu-20.04]
|
||||
|
@ -14,7 +14,7 @@ extern "C" {
|
||||
#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(
|
||||
cycles, benchmark::Counter::kAvgIterations | benchmark::Counter::kResultNoFormat);
|
||||
};
|
||||
|
@ -11,7 +11,7 @@
|
||||
#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(
|
||||
cycles, benchmark::Counter::kAvgIterations | benchmark::Counter::kResultNoFormat);
|
||||
};
|
||||
|
@ -5,12 +5,20 @@ use std::env;
|
||||
use std::path::Path;
|
||||
use threadpool::ThreadPool;
|
||||
use std::convert::TryInto;
|
||||
use aes_ctr_drbg::DrbgCtx;
|
||||
use aes_ctr_drbg::DrbgCtx as AesCtrDrbgCtx;
|
||||
use std::collections::HashMap;
|
||||
use std::thread;
|
||||
use std::sync::Mutex;
|
||||
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
|
||||
macro_rules! REG_SIGN {
|
||||
($ID:expr,$F:expr) => {
|
||||
@ -33,13 +41,88 @@ macro_rules! REG_KEM {
|
||||
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
|
||||
// is inserted in this map, just after thread starts
|
||||
// and removed after thread is finished. Operation
|
||||
// is synchronized.
|
||||
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
|
||||
@ -53,22 +136,21 @@ unsafe extern "C" fn randombytes(
|
||||
if let Some(drbg) = DRBGV.lock().unwrap().get_mut(&thread::current().id()) {
|
||||
drbg.get_random(&mut slice);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type ExecFn = fn(&TestVector);
|
||||
type ExecFn = fn(&TestVector) -> TestStatus;
|
||||
struct Register {
|
||||
kat: katwalk::reader::Kat,
|
||||
execfn: ExecFn,
|
||||
}
|
||||
|
||||
fn test_sign_vector(el: &TestVector) {
|
||||
fn test_sign_vector(el: &TestVector) -> TestStatus {
|
||||
let mut pk = Vec::new();
|
||||
let mut sk = Vec::new();
|
||||
let mut sm = Vec::new();
|
||||
|
||||
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 {
|
||||
@ -114,17 +196,18 @@ fn test_sign_vector(el: &TestVector) {
|
||||
el.sig.msg.as_ptr(), el.sig.msg.len() as u64,
|
||||
el.sig.pk.as_ptr()),
|
||||
true);
|
||||
return TestStatus::Processed;
|
||||
}
|
||||
}
|
||||
|
||||
fn test_kem_vector(el: &TestVector) {
|
||||
fn test_kem_vector(el: &TestVector) -> TestStatus {
|
||||
let mut pk = Vec::new();
|
||||
let mut sk = Vec::new();
|
||||
let mut ct = Vec::new();
|
||||
let mut ss = Vec::new();
|
||||
|
||||
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 {
|
||||
@ -161,6 +244,7 @@ fn test_kem_vector(el: &TestVector) {
|
||||
true);
|
||||
assert_eq!(ss, el.kem.ss);
|
||||
}
|
||||
return TestStatus::Processed;
|
||||
}
|
||||
|
||||
// KAT test register
|
||||
@ -221,30 +305,50 @@ const KATS: &'static[Register] = &[
|
||||
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
|
||||
let pool = ThreadPool::new(thc);
|
||||
let path = Path::new(&kat_dir);
|
||||
let mut code: u8 = 0;
|
||||
|
||||
for k in KATS.iter() {
|
||||
let tmp = kat_dir.clone();
|
||||
if !file_filter.is_empty() && !k.kat.kat_file.contains(file_filter) {
|
||||
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 || {
|
||||
DRBGV.lock().unwrap()
|
||||
.insert(thread::current().id(), DrbgCtx::new());
|
||||
let f = Path::new(&tmp.to_string()).join(k.kat.kat_file);
|
||||
let file = File::open(format!("{}", f.to_str().unwrap()));
|
||||
println!("Processing file: {}", Path::new(k.kat.kat_file).to_str().unwrap());
|
||||
let b = BufReader::new(file.unwrap());
|
||||
|
||||
for el in KatReader::new(b, k.kat.scheme_type, k.kat.scheme_id) {
|
||||
(k.execfn)(&el);
|
||||
.insert(thread::current().id(), CustomizableDrbgCtx::new());
|
||||
let proc = KatReader::new(buf, k.kat.scheme_type, k.kat.scheme_id);
|
||||
let iter = proc.into_iter();
|
||||
let mut processed = 0;
|
||||
let mut skipped = 0;
|
||||
for el in iter {
|
||||
let status = (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();
|
||||
return code;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -259,6 +363,7 @@ fn main() {
|
||||
argmap.insert(&args[i], &args[i+1]);
|
||||
}
|
||||
|
||||
// Number of threads to be used
|
||||
let thread_number: usize = match argmap.get(&"--threads".to_string()) {
|
||||
Some(n) => n.to_string().parse::<usize>().unwrap(),
|
||||
None => 4 /* by default 4 threads */,
|
||||
@ -270,8 +375,13 @@ fn main() {
|
||||
None => ""
|
||||
};
|
||||
|
||||
// Header for the results
|
||||
println!("Test file{:60}Processed Skipped", "");
|
||||
println!("------------------------------------------------------------------------------------------");
|
||||
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")
|
||||
};
|
||||
|
||||
|
Завантаження…
Посилання в новій задачі
Block a user