diff --git a/test/kat/Cargo.toml b/test/kat/Cargo.toml new file mode 100644 index 00000000..1d9db73a --- /dev/null +++ b/test/kat/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] + +members = [ + "pqclean-sys", + "cavptool", +] diff --git a/test/kat/cavptool/Cargo.toml b/test/kat/cavptool/Cargo.toml new file mode 100644 index 00000000..968cb999 --- /dev/null +++ b/test/kat/cavptool/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "cavptool" +version = "0.1.0" +authors = ["Kris Kwiatkowski "] +edition = "2018" + +[dependencies] +katwalk = "0.0.3" +pqclean-sys = { path = "../pqclean-sys" } +hex = "0.4.2" +threadpool = "1.8.1" diff --git a/test/kat/cavptool/src/main.rs b/test/kat/cavptool/src/main.rs new file mode 100644 index 00000000..63be84a2 --- /dev/null +++ b/test/kat/cavptool/src/main.rs @@ -0,0 +1,69 @@ +use katwalk::reader::{Kat, AlgType, TestVector, KatReader}; +use std::{fs::File, io::BufReader}; +use pqclean_sys::*; +use std::env; +use std::path::Path; +use threadpool::ThreadPool; + +const KAT_DIR : &'static str= "."; +type ExecFn = fn(&TestVector); +struct Register { + kat: katwalk::reader::Kat, + execfn: ExecFn, +} + +fn sign(el: &TestVector) { + + let mut msg_len: u64; + let mut msg = Vec::new(); + msg.resize(el.sig.msg.len(), 0); + msg.extend(el.sig.msg.iter().copied()); + unsafe { + msg_len = el.sig.msg.len() as u64; + assert_eq!( + PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open( + msg.as_mut_ptr(), &mut msg_len, + el.sig.sm.as_ptr(), el.sig.sm.len() as u64, + el.sig.pk.as_ptr()), + 0); + } +} + +// KAT test register +const REG: [Register; 1] = [ + Register{kat:Kat{scheme_type: AlgType::AlgSignature, scheme_id: 0, kat_file: "round3/dilithium/dilithium2/PQCsignKAT_2544.rsp"}, execfn: sign}, +]; + +fn execute(kat_dir: String) { + // Can't do multi-threads as DRBG context is global + let pool = ThreadPool::new(1); + for k in REG.iter() { + let tmp = kat_dir.clone(); + pool.execute(move || { + 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); + } + }); + } + pool.join(); +} + +fn main() { + let kat_dir: String; + let args: Vec = env::args().collect(); + if args.len() > 1 { + if args[1] == "--katdir" && args.len() == 3 { + kat_dir = args[2].to_string(); + } else { + panic!("Unrecognized argument"); + } + } else { + kat_dir = String::from(KAT_DIR); + } + execute(kat_dir); +} diff --git a/test/kat/pqclean-sys/Cargo.toml b/test/kat/pqclean-sys/Cargo.toml new file mode 100644 index 00000000..3d7fe85d --- /dev/null +++ b/test/kat/pqclean-sys/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "pqclean-sys" +version = "0.1.0" +authors = ["Kris Kwiatkowski "] +edition = "2018" +links = "pqclean_s" +build = "src/build.rs" + +[build-dependencies] +cmake = "0.1.31" +bindgen = "0.56.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/test/kat/pqclean-sys/src/bindings.rs b/test/kat/pqclean-sys/src/bindings.rs new file mode 100644 index 00000000..800f1886 --- /dev/null +++ b/test/kat/pqclean-sys/src/bindings.rs @@ -0,0 +1,295 @@ +/* automatically generated by rust-bindgen 0.56.0 */ + +pub const _STDINT_H: u32 = 1; +pub const _FEATURES_H: u32 = 1; +pub const _DEFAULT_SOURCE: u32 = 1; +pub const __GLIBC_USE_ISOC2X: u32 = 0; +pub const __USE_ISOC11: u32 = 1; +pub const __USE_ISOC99: u32 = 1; +pub const __USE_ISOC95: u32 = 1; +pub const __USE_POSIX_IMPLICITLY: u32 = 1; +pub const _POSIX_SOURCE: u32 = 1; +pub const _POSIX_C_SOURCE: u32 = 200809; +pub const __USE_POSIX: u32 = 1; +pub const __USE_POSIX2: u32 = 1; +pub const __USE_POSIX199309: u32 = 1; +pub const __USE_POSIX199506: u32 = 1; +pub const __USE_XOPEN2K: u32 = 1; +pub const __USE_XOPEN2K8: u32 = 1; +pub const _ATFILE_SOURCE: u32 = 1; +pub const __USE_MISC: u32 = 1; +pub const __USE_ATFILE: u32 = 1; +pub const __USE_FORTIFY_LEVEL: u32 = 0; +pub const __GLIBC_USE_DEPRECATED_GETS: u32 = 0; +pub const __GLIBC_USE_DEPRECATED_SCANF: u32 = 0; +pub const _STDC_PREDEF_H: u32 = 1; +pub const __STDC_IEC_559__: u32 = 1; +pub const __STDC_IEC_559_COMPLEX__: u32 = 1; +pub const __STDC_ISO_10646__: u32 = 201706; +pub const __GNU_LIBRARY__: u32 = 6; +pub const __GLIBC__: u32 = 2; +pub const __GLIBC_MINOR__: u32 = 33; +pub const _SYS_CDEFS_H: u32 = 1; +pub const __glibc_c99_flexarr_available: u32 = 1; +pub const __WORDSIZE: u32 = 64; +pub const __WORDSIZE_TIME64_COMPAT32: u32 = 1; +pub const __SYSCALL_WORDSIZE: u32 = 64; +pub const __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI: u32 = 0; +pub const __HAVE_GENERIC_SELECTION: u32 = 1; +pub const __GLIBC_USE_LIB_EXT2: u32 = 0; +pub const __GLIBC_USE_IEC_60559_BFP_EXT: u32 = 0; +pub const __GLIBC_USE_IEC_60559_BFP_EXT_C2X: u32 = 0; +pub const __GLIBC_USE_IEC_60559_FUNCS_EXT: u32 = 0; +pub const __GLIBC_USE_IEC_60559_FUNCS_EXT_C2X: u32 = 0; +pub const __GLIBC_USE_IEC_60559_TYPES_EXT: u32 = 0; +pub const _BITS_TYPES_H: u32 = 1; +pub const __TIMESIZE: u32 = 64; +pub const _BITS_TYPESIZES_H: u32 = 1; +pub const __OFF_T_MATCHES_OFF64_T: u32 = 1; +pub const __INO_T_MATCHES_INO64_T: u32 = 1; +pub const __RLIM_T_MATCHES_RLIM64_T: u32 = 1; +pub const __STATFS_MATCHES_STATFS64: u32 = 1; +pub const __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64: u32 = 1; +pub const __FD_SETSIZE: u32 = 1024; +pub const _BITS_TIME64_H: u32 = 1; +pub const _BITS_WCHAR_H: u32 = 1; +pub const _BITS_STDINT_INTN_H: u32 = 1; +pub const _BITS_STDINT_UINTN_H: u32 = 1; +pub const INT8_MIN: i32 = -128; +pub const INT16_MIN: i32 = -32768; +pub const INT32_MIN: i32 = -2147483648; +pub const INT8_MAX: u32 = 127; +pub const INT16_MAX: u32 = 32767; +pub const INT32_MAX: u32 = 2147483647; +pub const UINT8_MAX: u32 = 255; +pub const UINT16_MAX: u32 = 65535; +pub const UINT32_MAX: u32 = 4294967295; +pub const INT_LEAST8_MIN: i32 = -128; +pub const INT_LEAST16_MIN: i32 = -32768; +pub const INT_LEAST32_MIN: i32 = -2147483648; +pub const INT_LEAST8_MAX: u32 = 127; +pub const INT_LEAST16_MAX: u32 = 32767; +pub const INT_LEAST32_MAX: u32 = 2147483647; +pub const UINT_LEAST8_MAX: u32 = 255; +pub const UINT_LEAST16_MAX: u32 = 65535; +pub const UINT_LEAST32_MAX: u32 = 4294967295; +pub const INT_FAST8_MIN: i32 = -128; +pub const INT_FAST16_MIN: i64 = -9223372036854775808; +pub const INT_FAST32_MIN: i64 = -9223372036854775808; +pub const INT_FAST8_MAX: u32 = 127; +pub const INT_FAST16_MAX: u64 = 9223372036854775807; +pub const INT_FAST32_MAX: u64 = 9223372036854775807; +pub const UINT_FAST8_MAX: u32 = 255; +pub const UINT_FAST16_MAX: i32 = -1; +pub const UINT_FAST32_MAX: i32 = -1; +pub const INTPTR_MIN: i64 = -9223372036854775808; +pub const INTPTR_MAX: u64 = 9223372036854775807; +pub const UINTPTR_MAX: i32 = -1; +pub const PTRDIFF_MIN: i64 = -9223372036854775808; +pub const PTRDIFF_MAX: u64 = 9223372036854775807; +pub const SIG_ATOMIC_MIN: i32 = -2147483648; +pub const SIG_ATOMIC_MAX: u32 = 2147483647; +pub const SIZE_MAX: i32 = -1; +pub const WINT_MIN: u32 = 0; +pub const WINT_MAX: u32 = 4294967295; +pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_PUBLICKEYBYTES: u32 = 1312; +pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_SECRETKEYBYTES: u32 = 2544; +pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_BYTES: u32 = 2420; +pub const PQCLEAN_DILITHIUM2_CLEAN_CRYPTO_ALGNAME: &'static [u8; 11usize] = b"Dilithium2\0"; +pub type size_t = ::std::os::raw::c_ulong; +pub type wchar_t = ::std::os::raw::c_int; +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct max_align_t { + pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, + pub __bindgen_padding_0: u64, + pub __clang_max_align_nonce2: u128, +} +#[test] +fn bindgen_test_layout_max_align_t() { + assert_eq!( + ::std::mem::size_of::(), + 32usize, + concat!("Size of: ", stringify!(max_align_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 16usize, + concat!("Alignment of ", stringify!(max_align_t)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).__clang_max_align_nonce1 as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(max_align_t), + "::", + stringify!(__clang_max_align_nonce1) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).__clang_max_align_nonce2 as *const _ as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(max_align_t), + "::", + stringify!(__clang_max_align_nonce2) + ) + ); +} +pub type __u_char = ::std::os::raw::c_uchar; +pub type __u_short = ::std::os::raw::c_ushort; +pub type __u_int = ::std::os::raw::c_uint; +pub type __u_long = ::std::os::raw::c_ulong; +pub type __int8_t = ::std::os::raw::c_schar; +pub type __uint8_t = ::std::os::raw::c_uchar; +pub type __int16_t = ::std::os::raw::c_short; +pub type __uint16_t = ::std::os::raw::c_ushort; +pub type __int32_t = ::std::os::raw::c_int; +pub type __uint32_t = ::std::os::raw::c_uint; +pub type __int64_t = ::std::os::raw::c_long; +pub type __uint64_t = ::std::os::raw::c_ulong; +pub type __int_least8_t = __int8_t; +pub type __uint_least8_t = __uint8_t; +pub type __int_least16_t = __int16_t; +pub type __uint_least16_t = __uint16_t; +pub type __int_least32_t = __int32_t; +pub type __uint_least32_t = __uint32_t; +pub type __int_least64_t = __int64_t; +pub type __uint_least64_t = __uint64_t; +pub type __quad_t = ::std::os::raw::c_long; +pub type __u_quad_t = ::std::os::raw::c_ulong; +pub type __intmax_t = ::std::os::raw::c_long; +pub type __uintmax_t = ::std::os::raw::c_ulong; +pub type __dev_t = ::std::os::raw::c_ulong; +pub type __uid_t = ::std::os::raw::c_uint; +pub type __gid_t = ::std::os::raw::c_uint; +pub type __ino_t = ::std::os::raw::c_ulong; +pub type __ino64_t = ::std::os::raw::c_ulong; +pub type __mode_t = ::std::os::raw::c_uint; +pub type __nlink_t = ::std::os::raw::c_ulong; +pub type __off_t = ::std::os::raw::c_long; +pub type __off64_t = ::std::os::raw::c_long; +pub type __pid_t = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct __fsid_t { + pub __val: [::std::os::raw::c_int; 2usize], +} +#[test] +fn bindgen_test_layout___fsid_t() { + assert_eq!( + ::std::mem::size_of::<__fsid_t>(), + 8usize, + concat!("Size of: ", stringify!(__fsid_t)) + ); + assert_eq!( + ::std::mem::align_of::<__fsid_t>(), + 4usize, + concat!("Alignment of ", stringify!(__fsid_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<__fsid_t>())).__val as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__fsid_t), + "::", + stringify!(__val) + ) + ); +} +pub type __clock_t = ::std::os::raw::c_long; +pub type __rlim_t = ::std::os::raw::c_ulong; +pub type __rlim64_t = ::std::os::raw::c_ulong; +pub type __id_t = ::std::os::raw::c_uint; +pub type __time_t = ::std::os::raw::c_long; +pub type __useconds_t = ::std::os::raw::c_uint; +pub type __suseconds_t = ::std::os::raw::c_long; +pub type __suseconds64_t = ::std::os::raw::c_long; +pub type __daddr_t = ::std::os::raw::c_int; +pub type __key_t = ::std::os::raw::c_int; +pub type __clockid_t = ::std::os::raw::c_int; +pub type __timer_t = *mut ::std::os::raw::c_void; +pub type __blksize_t = ::std::os::raw::c_long; +pub type __blkcnt_t = ::std::os::raw::c_long; +pub type __blkcnt64_t = ::std::os::raw::c_long; +pub type __fsblkcnt_t = ::std::os::raw::c_ulong; +pub type __fsblkcnt64_t = ::std::os::raw::c_ulong; +pub type __fsfilcnt_t = ::std::os::raw::c_ulong; +pub type __fsfilcnt64_t = ::std::os::raw::c_ulong; +pub type __fsword_t = ::std::os::raw::c_long; +pub type __ssize_t = ::std::os::raw::c_long; +pub type __syscall_slong_t = ::std::os::raw::c_long; +pub type __syscall_ulong_t = ::std::os::raw::c_ulong; +pub type __loff_t = __off64_t; +pub type __caddr_t = *mut ::std::os::raw::c_char; +pub type __intptr_t = ::std::os::raw::c_long; +pub type __socklen_t = ::std::os::raw::c_uint; +pub type __sig_atomic_t = ::std::os::raw::c_int; +pub type int_least8_t = __int_least8_t; +pub type int_least16_t = __int_least16_t; +pub type int_least32_t = __int_least32_t; +pub type int_least64_t = __int_least64_t; +pub type uint_least8_t = __uint_least8_t; +pub type uint_least16_t = __uint_least16_t; +pub type uint_least32_t = __uint_least32_t; +pub type uint_least64_t = __uint_least64_t; +pub type int_fast8_t = ::std::os::raw::c_schar; +pub type int_fast16_t = ::std::os::raw::c_long; +pub type int_fast32_t = ::std::os::raw::c_long; +pub type int_fast64_t = ::std::os::raw::c_long; +pub type uint_fast8_t = ::std::os::raw::c_uchar; +pub type uint_fast16_t = ::std::os::raw::c_ulong; +pub type uint_fast32_t = ::std::os::raw::c_ulong; +pub type uint_fast64_t = ::std::os::raw::c_ulong; +pub type intmax_t = __intmax_t; +pub type uintmax_t = __uintmax_t; +extern "C" { + pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypair( + pk: *mut u8, + sk: *mut u8, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signature( + sig: *mut u8, + siglen: *mut size_t, + m: *const u8, + mlen: size_t, + sk: *const u8, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verify( + sig: *const u8, + siglen: size_t, + m: *const u8, + mlen: size_t, + pk: *const u8, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign( + sm: *mut u8, + smlen: *mut size_t, + m: *const u8, + mlen: size_t, + sk: *const u8, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn PQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open( + m: *mut u8, + mlen: *mut size_t, + sm: *const u8, + smlen: size_t, + pk: *const u8, + ) -> ::std::os::raw::c_int; +} diff --git a/test/kat/pqclean-sys/src/build.rs b/test/kat/pqclean-sys/src/build.rs new file mode 100644 index 00000000..1cba9ad5 --- /dev/null +++ b/test/kat/pqclean-sys/src/build.rs @@ -0,0 +1,36 @@ +extern crate cmake; +use cmake::Config; +extern crate bindgen; + +fn main() { + let dst = Config::new("../../../") + .profile("Release") + .very_verbose(true) + .build(); + + println!("cargo:rustc-link-search=native={}/lib", dst.display()); + println!("cargo:rustc-link-lib=dylib=pqclean"); + println!("cargo:rerun-if-changed=../../../src/sign/dilithium/dilithium2/clean/*"); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + // The input header we would like to generate + // bindings for. + .header("../../../src/sign/dilithium/dilithium2/clean/api.h") + // Point to PQClean include file + .clang_arg("-I../../../src/sign/dilithium/dilithium2/clean") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Add "Default" whenever possible + .derive_default(true) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + bindings + .write_to_file("src/bindings.rs") + .expect("Couldn't write bindings"); +} diff --git a/test/kat/pqclean-sys/src/lib.rs b/test/kat/pqclean-sys/src/lib.rs new file mode 100644 index 00000000..5e6c9215 --- /dev/null +++ b/test/kat/pqclean-sys/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!("bindings.rs"); \ No newline at end of file diff --git a/test/kat/pqclean-sys/src/wrapper.h b/test/kat/pqclean-sys/src/wrapper.h new file mode 100644 index 00000000..e69de29b