diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..3eb169df0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 diff --git a/Cargo.toml b/Cargo.toml index 469ed6636..974fb5e1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ serde_json = { version = "1.0" } serde = { version = "1.0", features = ["derive"] } hex = { version = "0.4.3", features = ["serde"] } pqcrypto-kyber = { version = "0.7.6", default-features = false } +libcrux-pqclean = { version = "*", path = "sys/pqclean" } # Benchmarking "RustCrypto" chacha20poly1305 = "0.10" diff --git a/benches/sha3.rs b/benches/sha3.rs index 30f3349c9..65b50502b 100644 --- a/benches/sha3.rs +++ b/benches/sha3.rs @@ -7,7 +7,7 @@ mod util; use util::*; macro_rules! impl_comp { - ($fun:ident, $libcrux:expr, $rust_crypto:ty, $openssl:expr) => { + ($fun:ident, $libcrux:expr, $rust_crypto:ty, $openssl:expr, $pqclean:expr) => { // Comparing libcrux performance for different payload sizes and other implementations. fn $fun(c: &mut Criterion) { const PAYLOAD_SIZES: [usize; 1] = [1024 * 1024 * 10]; @@ -65,6 +65,29 @@ macro_rules! impl_comp { ) }, ); + + if stringify!($fun) != "Sha3_224" { + group.bench_with_input( + BenchmarkId::new("PQClean", fmt(*payload_size)), + payload_size, + |b, payload_size| { + b.iter_batched( + || randombytes(*payload_size), + |payload| { + let mut digest = [0; libcrux::digest::digest_size($libcrux)]; + unsafe { + $pqclean( + digest.as_mut_ptr(), + payload.as_ptr() as _, + payload.len(), + ) + }; + }, + BatchSize::SmallInput, + ) + }, + ); + } } } }; @@ -74,25 +97,29 @@ impl_comp!( Sha3_224, Algorithm::Sha3_224, sha3::Sha3_224, - MessageDigest::sha3_224() + MessageDigest::sha3_224(), + libcrux_pqclean::sha3_256 // This is wrong, but it's not actually used. ); impl_comp!( Sha3_256, Algorithm::Sha3_256, sha3::Sha3_256, - MessageDigest::sha3_256() + MessageDigest::sha3_256(), + libcrux_pqclean::sha3_256 ); impl_comp!( Sha3_384, Algorithm::Sha3_384, sha3::Sha3_384, - MessageDigest::sha3_384() + MessageDigest::sha3_384(), + libcrux_pqclean::sha3_384 ); impl_comp!( Sha3_512, Algorithm::Sha3_512, sha3::Sha3_512, - MessageDigest::sha3_512() + MessageDigest::sha3_512(), + libcrux_pqclean::sha3_512 ); fn benchmarks(c: &mut Criterion) { diff --git a/sys/pqclean/.gitignore b/sys/pqclean/.gitignore new file mode 100644 index 000000000..2c96eb1b6 --- /dev/null +++ b/sys/pqclean/.gitignore @@ -0,0 +1,2 @@ +target/ +Cargo.lock diff --git a/sys/pqclean/Cargo.toml b/sys/pqclean/Cargo.toml new file mode 100644 index 000000000..c10ec849a --- /dev/null +++ b/sys/pqclean/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "libcrux-pqclean" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[build-dependencies] +cc = { version = "1.0", features = ["parallel"] } +bindgen = "0.66" +fs_extra = "1.2" diff --git a/sys/pqclean/Readme.md b/sys/pqclean/Readme.md new file mode 100644 index 000000000..50efedf52 --- /dev/null +++ b/sys/pqclean/Readme.md @@ -0,0 +1,5 @@ +# PQClean sys + +A simple sys crate to benchmark pqclean clode that is not exposed to Rust, like SHA3. + +The code is taken from https://github.com/PQClean/PQClean/commit/ef80f51badac27b78f8e0ef26f23cbd71ca0f283. diff --git a/sys/pqclean/build.rs b/sys/pqclean/build.rs new file mode 100644 index 000000000..e2e5557d4 --- /dev/null +++ b/sys/pqclean/build.rs @@ -0,0 +1,98 @@ +use std::{env, path::Path}; + +fn copy_files(home_path: &Path, out_path: &Path) { + let mut options = fs_extra::dir::CopyOptions::new(); + options.overwrite = true; + fs_extra::dir::copy(home_path.join("c"), out_path, &options).unwrap(); +} + +#[cfg(not(windows))] +fn create_bindings(home_dir: &Path) { + let c_dir = home_dir.join("c"); + let clang_args = vec![format!("-I{}", c_dir.display())]; + + let bindings = bindgen::Builder::default() + // Header to wrap headers + .header("c/fips202.h") + // Set include paths for headers + .clang_args(clang_args) + // Include the things we want + .allowlist_function("shake.*") + .allowlist_function("sha3.*") + .allowlist_type("sha3.*") + .allowlist_type("shake.*") + .allowlist_type("SHAKE.*") + .allowlist_type("SHA3.*") + .allowlist_var("SHAKE.*") + .allowlist_var("SHA3.*") + // Disable tests to avoid warnings and keep it portable + .layout_tests(false) + // Generate bindings + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + .use_core() + .generate() + .expect("Unable to generate bindings"); + + let home_bindings = home_dir.join("src/bindings.rs"); + bindings + .write_to_file(home_bindings) + .expect("Couldn't write bindings!"); +} + +#[cfg(windows)] +fn create_bindings(_: &Path) {} + +fn compile_files(library_name: &str, files: &[String], out_path: &Path, args: &[String]) { + let c_dir = out_path.join("c"); + + let mut build = cc::Build::new(); + build + .files(files.iter().map(|fname| c_dir.join(fname))) + .warnings_into_errors(true) + .no_default_flags(true); + + build.include(c_dir.join("include")); + build.flag("-O3").flag("-c"); + for arg in args { + build.flag(arg); + } + + build.compile(library_name); +} + +fn build(out_path: &Path) { + let files = vec!["fips202.c".to_string()]; + let args = vec![]; + compile_files("libpqclean.a", &files, out_path, &args); +} + +pub fn main() -> Result<(), u8> { + // Get ENV variables + let home_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let home_path = Path::new(&home_dir); + let out_dir = env::var("OUT_DIR").unwrap(); + let out_path = Path::new(&out_dir); + + // Moving C/ASM code to output to make build easier. + copy_files(home_path, out_path); + + // Build the C/ASM files + build(out_path); + + // Set library name to look up + let library_name = "pqclean"; + + // Set re-run trigger for all of s + println!("cargo:rerun-if-changed=cs"); + + // Generate new bindings. This is a no-op on Windows. + create_bindings(home_path); + + // Link hacl library. + let mode = "static"; + println!("cargo:rustc-link-lib={}={}", mode, library_name); + println!("cargo:rustc-link-search=native={}", out_path.display()); + println!("cargo:lib={}", out_path.display()); + + Ok(()) +} diff --git a/sys/pqclean/c/fips202.c b/sys/pqclean/c/fips202.c new file mode 100644 index 000000000..6a13446b0 --- /dev/null +++ b/sys/pqclean/c/fips202.c @@ -0,0 +1,929 @@ +/* Based on the public domain implementation in + * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html + * by Ronny Van Keer + * and the public domain "TweetFips202" implementation + * from https://twitter.com/tweetfips202 + * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ + +#include +#include +#include +#include + +#include "fips202.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset)))) + +/************************************************* + * Name: load64 + * + * Description: Load 8 bytes into uint64_t in little-endian order + * + * Arguments: - const uint8_t *x: pointer to input byte array + * + * Returns the loaded 64-bit unsigned integer + **************************************************/ +static uint64_t load64(const uint8_t *x) { + uint64_t r = 0; + for (size_t i = 0; i < 8; ++i) { + r |= (uint64_t)x[i] << 8 * i; + } + + return r; +} + +/************************************************* + * Name: store64 + * + * Description: Store a 64-bit integer to a byte array in little-endian order + * + * Arguments: - uint8_t *x: pointer to the output byte array + * - uint64_t u: input 64-bit unsigned integer + **************************************************/ +static void store64(uint8_t *x, uint64_t u) { + for (size_t i = 0; i < 8; ++i) { + x[i] = (uint8_t) (u >> 8 * i); + } +} + +/* Keccak round constants */ +static const uint64_t KeccakF_RoundConstants[NROUNDS] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, + 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, + 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL +}; + +/************************************************* + * Name: KeccakF1600_StatePermute + * + * Description: The Keccak F1600 Permutation + * + * Arguments: - uint64_t *state: pointer to input/output Keccak state + **************************************************/ +static void KeccakF1600_StatePermute(uint64_t *state) { + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + uint64_t BCa, BCe, BCi, BCo, BCu; + uint64_t Da, De, Di, Do, Du; + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + // copyFromState(A, state) + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < NROUNDS; round += 2) { + // prepareTheta + BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; + BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + // thetaRhoPiChiIotaPrepareTheta(round , A, E) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = ROL(Age, 44); + Aki ^= Di; + BCi = ROL(Aki, 43); + Amo ^= Do; + BCo = ROL(Amo, 21); + Asu ^= Du; + BCu = ROL(Asu, 14); + Eba = BCa ^ ((~BCe) & BCi); + Eba ^= KeccakF_RoundConstants[round]; + Ebe = BCe ^ ((~BCi) & BCo); + Ebi = BCi ^ ((~BCo) & BCu); + Ebo = BCo ^ ((~BCu) & BCa); + Ebu = BCu ^ ((~BCa) & BCe); + + Abo ^= Do; + BCa = ROL(Abo, 28); + Agu ^= Du; + BCe = ROL(Agu, 20); + Aka ^= Da; + BCi = ROL(Aka, 3); + Ame ^= De; + BCo = ROL(Ame, 45); + Asi ^= Di; + BCu = ROL(Asi, 61); + Ega = BCa ^ ((~BCe) & BCi); + Ege = BCe ^ ((~BCi) & BCo); + Egi = BCi ^ ((~BCo) & BCu); + Ego = BCo ^ ((~BCu) & BCa); + Egu = BCu ^ ((~BCa) & BCe); + + Abe ^= De; + BCa = ROL(Abe, 1); + Agi ^= Di; + BCe = ROL(Agi, 6); + Ako ^= Do; + BCi = ROL(Ako, 25); + Amu ^= Du; + BCo = ROL(Amu, 8); + Asa ^= Da; + BCu = ROL(Asa, 18); + Eka = BCa ^ ((~BCe) & BCi); + Eke = BCe ^ ((~BCi) & BCo); + Eki = BCi ^ ((~BCo) & BCu); + Eko = BCo ^ ((~BCu) & BCa); + Eku = BCu ^ ((~BCa) & BCe); + + Abu ^= Du; + BCa = ROL(Abu, 27); + Aga ^= Da; + BCe = ROL(Aga, 36); + Ake ^= De; + BCi = ROL(Ake, 10); + Ami ^= Di; + BCo = ROL(Ami, 15); + Aso ^= Do; + BCu = ROL(Aso, 56); + Ema = BCa ^ ((~BCe) & BCi); + Eme = BCe ^ ((~BCi) & BCo); + Emi = BCi ^ ((~BCo) & BCu); + Emo = BCo ^ ((~BCu) & BCa); + Emu = BCu ^ ((~BCa) & BCe); + + Abi ^= Di; + BCa = ROL(Abi, 62); + Ago ^= Do; + BCe = ROL(Ago, 55); + Aku ^= Du; + BCi = ROL(Aku, 39); + Ama ^= Da; + BCo = ROL(Ama, 41); + Ase ^= De; + BCu = ROL(Ase, 2); + Esa = BCa ^ ((~BCe) & BCi); + Ese = BCe ^ ((~BCi) & BCo); + Esi = BCi ^ ((~BCo) & BCu); + Eso = BCo ^ ((~BCu) & BCa); + Esu = BCu ^ ((~BCa) & BCe); + + // prepareTheta + BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = ROL(Ege, 44); + Eki ^= Di; + BCi = ROL(Eki, 43); + Emo ^= Do; + BCo = ROL(Emo, 21); + Esu ^= Du; + BCu = ROL(Esu, 14); + Aba = BCa ^ ((~BCe) & BCi); + Aba ^= KeccakF_RoundConstants[round + 1]; + Abe = BCe ^ ((~BCi) & BCo); + Abi = BCi ^ ((~BCo) & BCu); + Abo = BCo ^ ((~BCu) & BCa); + Abu = BCu ^ ((~BCa) & BCe); + + Ebo ^= Do; + BCa = ROL(Ebo, 28); + Egu ^= Du; + BCe = ROL(Egu, 20); + Eka ^= Da; + BCi = ROL(Eka, 3); + Eme ^= De; + BCo = ROL(Eme, 45); + Esi ^= Di; + BCu = ROL(Esi, 61); + Aga = BCa ^ ((~BCe) & BCi); + Age = BCe ^ ((~BCi) & BCo); + Agi = BCi ^ ((~BCo) & BCu); + Ago = BCo ^ ((~BCu) & BCa); + Agu = BCu ^ ((~BCa) & BCe); + + Ebe ^= De; + BCa = ROL(Ebe, 1); + Egi ^= Di; + BCe = ROL(Egi, 6); + Eko ^= Do; + BCi = ROL(Eko, 25); + Emu ^= Du; + BCo = ROL(Emu, 8); + Esa ^= Da; + BCu = ROL(Esa, 18); + Aka = BCa ^ ((~BCe) & BCi); + Ake = BCe ^ ((~BCi) & BCo); + Aki = BCi ^ ((~BCo) & BCu); + Ako = BCo ^ ((~BCu) & BCa); + Aku = BCu ^ ((~BCa) & BCe); + + Ebu ^= Du; + BCa = ROL(Ebu, 27); + Ega ^= Da; + BCe = ROL(Ega, 36); + Eke ^= De; + BCi = ROL(Eke, 10); + Emi ^= Di; + BCo = ROL(Emi, 15); + Eso ^= Do; + BCu = ROL(Eso, 56); + Ama = BCa ^ ((~BCe) & BCi); + Ame = BCe ^ ((~BCi) & BCo); + Ami = BCi ^ ((~BCo) & BCu); + Amo = BCo ^ ((~BCu) & BCa); + Amu = BCu ^ ((~BCa) & BCe); + + Ebi ^= Di; + BCa = ROL(Ebi, 62); + Ego ^= Do; + BCe = ROL(Ego, 55); + Eku ^= Du; + BCi = ROL(Eku, 39); + Ema ^= Da; + BCo = ROL(Ema, 41); + Ese ^= De; + BCu = ROL(Ese, 2); + Asa = BCa ^ ((~BCe) & BCi); + Ase = BCe ^ ((~BCi) & BCo); + Asi = BCi ^ ((~BCo) & BCu); + Aso = BCo ^ ((~BCu) & BCa); + Asu = BCu ^ ((~BCa) & BCe); + } + + // copyToState(state, A) + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +/************************************************* + * Name: keccak_absorb + * + * Description: Absorb step of Keccak; + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *m: pointer to input to be absorbed into s + * - size_t mlen: length of input in bytes + * - uint8_t p: domain-separation byte for different + * Keccak-derived functions + **************************************************/ +static void keccak_absorb(uint64_t *s, uint32_t r, const uint8_t *m, + size_t mlen, uint8_t p) { + size_t i; + uint8_t t[200]; + + /* Zero state */ + for (i = 0; i < 25; ++i) { + s[i] = 0; + } + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[i] ^= load64(m + 8 * i); + } + + KeccakF1600_StatePermute(s); + mlen -= r; + m += r; + } + + for (i = 0; i < r; ++i) { + t[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t[i] = m[i]; + } + t[i] = p; + t[r - 1] |= 128; + for (i = 0; i < r / 8; ++i) { + s[i] ^= load64(t + 8 * i); + } +} + +/************************************************* + * Name: keccak_squeezeblocks + * + * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *h: pointer to output blocks + * - size_t nblocks: number of blocks to be + * squeezed (written to h) + * - uint64_t *s: pointer to input/output Keccak state + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_squeezeblocks(uint8_t *h, size_t nblocks, + uint64_t *s, uint32_t r) { + while (nblocks > 0) { + KeccakF1600_StatePermute(s); + for (size_t i = 0; i < (r >> 3); i++) { + store64(h + 8 * i, s[i]); + } + h += r; + nblocks--; + } +} + +/************************************************* + * Name: keccak_inc_init + * + * Description: Initializes the incremental Keccak state to zero. + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + **************************************************/ +static void keccak_inc_init(uint64_t *s_inc) { + size_t i; + + for (i = 0; i < 25; ++i) { + s_inc[i] = 0; + } + s_inc[25] = 0; +} + +/************************************************* + * Name: keccak_inc_absorb + * + * Description: Incremental keccak absorb + * Preceded by keccak_inc_init, succeeded by keccak_inc_finalize + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *m: pointer to input to be absorbed into s + * - size_t mlen: length of input in bytes + **************************************************/ +static void keccak_inc_absorb(uint64_t *s_inc, uint32_t r, const uint8_t *m, + size_t mlen) { + size_t i; + + /* Recall that s_inc[25] is the non-absorbed bytes xored into the state */ + while (mlen + s_inc[25] >= r) { + for (i = 0; i < r - (uint32_t)s_inc[25]; i++) { + /* Take the i'th byte from message + xor with the s_inc[25] + i'th byte of the state; little-endian */ + s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); + } + mlen -= (size_t)(r - s_inc[25]); + m += r - s_inc[25]; + s_inc[25] = 0; + + KeccakF1600_StatePermute(s_inc); + } + + for (i = 0; i < mlen; i++) { + s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); + } + s_inc[25] += mlen; +} + +/************************************************* + * Name: keccak_inc_finalize + * + * Description: Finalizes Keccak absorb phase, prepares for squeezing + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - uint8_t p: domain-separation byte for different + * Keccak-derived functions + **************************************************/ +static void keccak_inc_finalize(uint64_t *s_inc, uint32_t r, uint8_t p) { + /* After keccak_inc_absorb, we are guaranteed that s_inc[25] < r, + so we can always use one more byte for p in the current state. */ + s_inc[s_inc[25] >> 3] ^= (uint64_t)p << (8 * (s_inc[25] & 0x07)); + s_inc[(r - 1) >> 3] ^= (uint64_t)128 << (8 * ((r - 1) & 0x07)); + s_inc[25] = 0; +} + +/************************************************* + * Name: keccak_inc_squeeze + * + * Description: Incremental Keccak squeeze; can be called on byte-level + * + * Arguments: - uint8_t *h: pointer to output bytes + * - size_t outlen: number of bytes to be squeezed + * - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_inc_squeeze(uint8_t *h, size_t outlen, + uint64_t *s_inc, uint32_t r) { + size_t i; + + /* First consume any bytes we still have sitting around */ + for (i = 0; i < outlen && i < s_inc[25]; i++) { + /* There are s_inc[25] bytes left, so r - s_inc[25] is the first + available byte. We consume from there, i.e., up to r. */ + h[i] = (uint8_t)(s_inc[(r - s_inc[25] + i) >> 3] >> (8 * ((r - s_inc[25] + i) & 0x07))); + } + h += i; + outlen -= i; + s_inc[25] -= i; + + /* Then squeeze the remaining necessary blocks */ + while (outlen > 0) { + KeccakF1600_StatePermute(s_inc); + + for (i = 0; i < outlen && i < r; i++) { + h[i] = (uint8_t)(s_inc[i >> 3] >> (8 * (i & 0x07))); + } + h += i; + outlen -= i; + s_inc[25] = r - i; + } +} + +void shake128_inc_init(shake128incctx *state) { + state->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHAKE128_RATE, input, inlen); +} + +void shake128_inc_finalize(shake128incctx *state) { + keccak_inc_finalize(state->ctx, SHAKE128_RATE, 0x1F); +} + +void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state) { + keccak_inc_squeeze(output, outlen, state->ctx, SHAKE128_RATE); +} + +void shake128_inc_ctx_clone(shake128incctx *dest, const shake128incctx *src) { + dest->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void shake128_inc_ctx_release(shake128incctx *state) { + free(state->ctx); +} + +void shake256_inc_init(shake256incctx *state) { + state->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHAKE256_RATE, input, inlen); +} + +void shake256_inc_finalize(shake256incctx *state) { + keccak_inc_finalize(state->ctx, SHAKE256_RATE, 0x1F); +} + +void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state) { + keccak_inc_squeeze(output, outlen, state->ctx, SHAKE256_RATE); +} + +void shake256_inc_ctx_clone(shake256incctx *dest, const shake256incctx *src) { + dest->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void shake256_inc_ctx_release(shake256incctx *state) { + free(state->ctx); +} + + +/************************************************* + * Name: shake128_absorb + * + * Description: Absorb step of the SHAKE128 XOF. + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - const uint8_t *input: pointer to input to be absorbed + * into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen) { + state->ctx = malloc(PQC_SHAKECTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_absorb(state->ctx, SHAKE128_RATE, input, inlen, 0x1F); +} + +/************************************************* + * Name: shake128_squeezeblocks + * + * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of + * SHAKE128_RATE bytes each. Modifies the state. Can be called + * multiple times to keep squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *output: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed + * (written to output) + * - shake128ctx *state: pointer to input/output Keccak state + **************************************************/ +void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state) { + keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE128_RATE); +} + +void shake128_ctx_clone(shake128ctx *dest, const shake128ctx *src) { + dest->ctx = malloc(PQC_SHAKECTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKECTX_BYTES); +} + +/** Release the allocated state. Call only once. */ +void shake128_ctx_release(shake128ctx *state) { + free(state->ctx); +} + +/************************************************* + * Name: shake256_absorb + * + * Description: Absorb step of the SHAKE256 XOF. + * non-incremental, starts by zeroeing the state. + * + * Arguments: - shake256ctx *state: pointer to (uninitialized) output Keccak state + * - const uint8_t *input: pointer to input to be absorbed + * into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen) { + state->ctx = malloc(PQC_SHAKECTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_absorb(state->ctx, SHAKE256_RATE, input, inlen, 0x1F); +} + +/************************************************* + * Name: shake256_squeezeblocks + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of + * SHAKE256_RATE bytes each. Modifies the state. Can be called + * multiple times to keep squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *output: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed + * (written to output) + * - shake256ctx *state: pointer to input/output Keccak state + **************************************************/ +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state) { + keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE256_RATE); +} + +void shake256_ctx_clone(shake256ctx *dest, const shake256ctx *src) { + dest->ctx = malloc(PQC_SHAKECTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKECTX_BYTES); +} + +/** Release the allocated state. Call only once. */ +void shake256_ctx_release(shake256ctx *state) { + free(state->ctx); +} + +/************************************************* + * Name: shake128 + * + * Description: SHAKE128 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen) { + size_t nblocks = outlen / SHAKE128_RATE; + uint8_t t[SHAKE128_RATE]; + shake128ctx s; + + shake128_absorb(&s, input, inlen); + shake128_squeezeblocks(output, nblocks, &s); + + output += nblocks * SHAKE128_RATE; + outlen -= nblocks * SHAKE128_RATE; + + if (outlen) { + shake128_squeezeblocks(t, 1, &s); + for (size_t i = 0; i < outlen; ++i) { + output[i] = t[i]; + } + } + shake128_ctx_release(&s); +} + +/************************************************* + * Name: shake256 + * + * Description: SHAKE256 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen) { + size_t nblocks = outlen / SHAKE256_RATE; + uint8_t t[SHAKE256_RATE]; + shake256ctx s; + + shake256_absorb(&s, input, inlen); + shake256_squeezeblocks(output, nblocks, &s); + + output += nblocks * SHAKE256_RATE; + outlen -= nblocks * SHAKE256_RATE; + + if (outlen) { + shake256_squeezeblocks(t, 1, &s); + for (size_t i = 0; i < outlen; ++i) { + output[i] = t[i]; + } + } + shake256_ctx_release(&s); +} + +void sha3_256_inc_init(sha3_256incctx *state) { + state->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void sha3_256_inc_ctx_clone(sha3_256incctx *dest, const sha3_256incctx *src) { + dest->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void sha3_256_inc_ctx_release(sha3_256incctx *state) { + free(state->ctx); +} + +void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHA3_256_RATE, input, inlen); +} + +void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state) { + uint8_t t[SHA3_256_RATE]; + keccak_inc_finalize(state->ctx, SHA3_256_RATE, 0x06); + + keccak_squeezeblocks(t, 1, state->ctx, SHA3_256_RATE); + + sha3_256_inc_ctx_release(state); + + for (size_t i = 0; i < 32; i++) { + output[i] = t[i]; + } +} + +/************************************************* + * Name: sha3_256 + * + * Description: SHA3-256 with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) { + uint64_t s[25]; + uint8_t t[SHA3_256_RATE]; + + /* Absorb input */ + keccak_absorb(s, SHA3_256_RATE, input, inlen, 0x06); + + /* Squeeze output */ + keccak_squeezeblocks(t, 1, s, SHA3_256_RATE); + + for (size_t i = 0; i < 32; i++) { + output[i] = t[i]; + } +} + +void sha3_384_inc_init(sha3_384incctx *state) { + state->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void sha3_384_inc_ctx_clone(sha3_384incctx *dest, const sha3_384incctx *src) { + dest->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void sha3_384_inc_absorb(sha3_384incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHA3_384_RATE, input, inlen); +} + +void sha3_384_inc_ctx_release(sha3_384incctx *state) { + free(state->ctx); +} + +void sha3_384_inc_finalize(uint8_t *output, sha3_384incctx *state) { + uint8_t t[SHA3_384_RATE]; + keccak_inc_finalize(state->ctx, SHA3_384_RATE, 0x06); + + keccak_squeezeblocks(t, 1, state->ctx, SHA3_384_RATE); + + sha3_384_inc_ctx_release(state); + + for (size_t i = 0; i < 48; i++) { + output[i] = t[i]; + } +} + +/************************************************* + * Name: sha3_384 + * + * Description: SHA3-256 with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) { + uint64_t s[25]; + uint8_t t[SHA3_384_RATE]; + + /* Absorb input */ + keccak_absorb(s, SHA3_384_RATE, input, inlen, 0x06); + + /* Squeeze output */ + keccak_squeezeblocks(t, 1, s, SHA3_384_RATE); + + for (size_t i = 0; i < 48; i++) { + output[i] = t[i]; + } +} + +void sha3_512_inc_init(sha3_512incctx *state) { + state->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void sha3_512_inc_ctx_clone(sha3_512incctx *dest, const sha3_512incctx *src) { + dest->ctx = malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHA3_512_RATE, input, inlen); +} + +void sha3_512_inc_ctx_release(sha3_512incctx *state) { + free(state->ctx); +} + +void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state) { + uint8_t t[SHA3_512_RATE]; + keccak_inc_finalize(state->ctx, SHA3_512_RATE, 0x06); + + keccak_squeezeblocks(t, 1, state->ctx, SHA3_512_RATE); + + sha3_512_inc_ctx_release(state); + + for (size_t i = 0; i < 64; i++) { + output[i] = t[i]; + } +} + +/************************************************* + * Name: sha3_512 + * + * Description: SHA3-512 with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen) { + uint64_t s[25]; + uint8_t t[SHA3_512_RATE]; + + /* Absorb input */ + keccak_absorb(s, SHA3_512_RATE, input, inlen, 0x06); + + /* Squeeze output */ + keccak_squeezeblocks(t, 1, s, SHA3_512_RATE); + + for (size_t i = 0; i < 64; i++) { + output[i] = t[i]; + } +} diff --git a/sys/pqclean/c/fips202.h b/sys/pqclean/c/fips202.h new file mode 100644 index 000000000..d3fda8119 --- /dev/null +++ b/sys/pqclean/c/fips202.h @@ -0,0 +1,167 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_384_RATE 104 +#define SHA3_512_RATE 72 + + +#define PQC_SHAKEINCCTX_BYTES (sizeof(uint64_t)*26) +#define PQC_SHAKECTX_BYTES (sizeof(uint64_t)*25) + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} shake128incctx; + +// Context for non-incremental API +typedef struct { + uint64_t* ctx; +} shake128ctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} shake256incctx; + +// Context for non-incremental API +typedef struct { + uint64_t* ctx; +} shake256ctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} sha3_256incctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} sha3_384incctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} sha3_512incctx; + +/* Initialize the state and absorb the provided input. + * + * This function does not support being called multiple times + * with the same state. + */ +void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state); +/* Free the state */ +void shake128_ctx_release(shake128ctx *state); +/* Copy the state. */ +void shake128_ctx_clone(shake128ctx *dest, const shake128ctx *src); + +/* Initialize incremental hashing API */ +void shake128_inc_init(shake128incctx *state); +/* Absorb more information into the XOF. + * + * Can be called multiple times. + */ +void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); +/* Finalize the XOF for squeezing */ +void shake128_inc_finalize(shake128incctx *state); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); +/* Copy the context of the SHAKE128 XOF */ +void shake128_inc_ctx_clone(shake128incctx* dest, const shake128incctx *src); +/* Free the context of the SHAKE128 XOF */ +void shake128_inc_ctx_release(shake128incctx *state); + +/* Initialize the state and absorb the provided input. + * + * This function does not support being called multiple times + * with the same state. + */ +void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state); +/* Free the context held by this XOF */ +void shake256_ctx_release(shake256ctx *state); +/* Copy the context held by this XOF */ +void shake256_ctx_clone(shake256ctx *dest, const shake256ctx *src); + +/* Initialize incremental hashing API */ +void shake256_inc_init(shake256incctx *state); +void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); +/* Prepares for squeeze phase */ +void shake256_inc_finalize(shake256incctx *state); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); +/* Copy the state */ +void shake256_inc_ctx_clone(shake256incctx* dest, const shake256incctx *src); +/* Free the state */ +void shake256_inc_ctx_release(shake256incctx *state); + +/* One-stop SHAKE128 call */ +void shake128(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen); + +/* One-stop SHAKE256 call */ +void shake256(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_256_inc_init(sha3_256incctx *state); +/* Absorb blocks into SHA3 */ +void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state); +/* Copy the context */ +void sha3_256_inc_ctx_clone(sha3_256incctx *dest, const sha3_256incctx *src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_256_inc_ctx_release(sha3_256incctx *state); + +void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_384_inc_init(sha3_384incctx *state); +/* Absorb blocks into SHA3 */ +void sha3_384_inc_absorb(sha3_384incctx *state, const uint8_t *input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_384_inc_finalize(uint8_t *output, sha3_384incctx *state); +/* Copy the context */ +void sha3_384_inc_ctx_clone(sha3_384incctx *dest, const sha3_384incctx *src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_384_inc_ctx_release(sha3_384incctx *state); + +/* One-stop SHA3-384 shop */ +void sha3_384(uint8_t *output, const uint8_t *input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_512_inc_init(sha3_512incctx *state); +/* Absorb blocks into SHA3 */ +void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state); +/* Copy the context */ +void sha3_512_inc_ctx_clone(sha3_512incctx *dest, const sha3_512incctx *src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_512_inc_ctx_release(sha3_512incctx *state); + +/* One-stop SHA3-512 shop */ +void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); + +#endif diff --git a/sys/pqclean/src/bindings.rs b/sys/pqclean/src/bindings.rs new file mode 100644 index 000000000..636875539 --- /dev/null +++ b/sys/pqclean/src/bindings.rs @@ -0,0 +1,162 @@ +/* automatically generated by rust-bindgen 0.66.1 */ + +pub const SHAKE128_RATE: u32 = 168; +pub const SHAKE256_RATE: u32 = 136; +pub const SHA3_256_RATE: u32 = 136; +pub const SHA3_384_RATE: u32 = 104; +pub const SHA3_512_RATE: u32 = 72; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct shake128incctx { + pub ctx: *mut u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct shake128ctx { + pub ctx: *mut u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct shake256incctx { + pub ctx: *mut u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct shake256ctx { + pub ctx: *mut u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct sha3_256incctx { + pub ctx: *mut u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct sha3_384incctx { + pub ctx: *mut u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct sha3_512incctx { + pub ctx: *mut u64, +} +extern "C" { + pub fn shake128_absorb(state: *mut shake128ctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn shake128_squeezeblocks(output: *mut u8, nblocks: usize, state: *mut shake128ctx); +} +extern "C" { + pub fn shake128_ctx_release(state: *mut shake128ctx); +} +extern "C" { + pub fn shake128_ctx_clone(dest: *mut shake128ctx, src: *const shake128ctx); +} +extern "C" { + pub fn shake128_inc_init(state: *mut shake128incctx); +} +extern "C" { + pub fn shake128_inc_absorb(state: *mut shake128incctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn shake128_inc_finalize(state: *mut shake128incctx); +} +extern "C" { + pub fn shake128_inc_squeeze(output: *mut u8, outlen: usize, state: *mut shake128incctx); +} +extern "C" { + pub fn shake128_inc_ctx_clone(dest: *mut shake128incctx, src: *const shake128incctx); +} +extern "C" { + pub fn shake128_inc_ctx_release(state: *mut shake128incctx); +} +extern "C" { + pub fn shake256_absorb(state: *mut shake256ctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn shake256_squeezeblocks(output: *mut u8, nblocks: usize, state: *mut shake256ctx); +} +extern "C" { + pub fn shake256_ctx_release(state: *mut shake256ctx); +} +extern "C" { + pub fn shake256_ctx_clone(dest: *mut shake256ctx, src: *const shake256ctx); +} +extern "C" { + pub fn shake256_inc_init(state: *mut shake256incctx); +} +extern "C" { + pub fn shake256_inc_absorb(state: *mut shake256incctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn shake256_inc_finalize(state: *mut shake256incctx); +} +extern "C" { + pub fn shake256_inc_squeeze(output: *mut u8, outlen: usize, state: *mut shake256incctx); +} +extern "C" { + pub fn shake256_inc_ctx_clone(dest: *mut shake256incctx, src: *const shake256incctx); +} +extern "C" { + pub fn shake256_inc_ctx_release(state: *mut shake256incctx); +} +extern "C" { + pub fn shake128(output: *mut u8, outlen: usize, input: *const u8, inlen: usize); +} +extern "C" { + pub fn shake256(output: *mut u8, outlen: usize, input: *const u8, inlen: usize); +} +extern "C" { + pub fn sha3_256_inc_init(state: *mut sha3_256incctx); +} +extern "C" { + pub fn sha3_256_inc_absorb(state: *mut sha3_256incctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn sha3_256_inc_finalize(output: *mut u8, state: *mut sha3_256incctx); +} +extern "C" { + pub fn sha3_256_inc_ctx_clone(dest: *mut sha3_256incctx, src: *const sha3_256incctx); +} +extern "C" { + pub fn sha3_256_inc_ctx_release(state: *mut sha3_256incctx); +} +extern "C" { + pub fn sha3_256(output: *mut u8, input: *const u8, inlen: usize); +} +extern "C" { + pub fn sha3_384_inc_init(state: *mut sha3_384incctx); +} +extern "C" { + pub fn sha3_384_inc_absorb(state: *mut sha3_384incctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn sha3_384_inc_finalize(output: *mut u8, state: *mut sha3_384incctx); +} +extern "C" { + pub fn sha3_384_inc_ctx_clone(dest: *mut sha3_384incctx, src: *const sha3_384incctx); +} +extern "C" { + pub fn sha3_384_inc_ctx_release(state: *mut sha3_384incctx); +} +extern "C" { + pub fn sha3_384(output: *mut u8, input: *const u8, inlen: usize); +} +extern "C" { + pub fn sha3_512_inc_init(state: *mut sha3_512incctx); +} +extern "C" { + pub fn sha3_512_inc_absorb(state: *mut sha3_512incctx, input: *const u8, inlen: usize); +} +extern "C" { + pub fn sha3_512_inc_finalize(output: *mut u8, state: *mut sha3_512incctx); +} +extern "C" { + pub fn sha3_512_inc_ctx_clone(dest: *mut sha3_512incctx, src: *const sha3_512incctx); +} +extern "C" { + pub fn sha3_512_inc_ctx_release(state: *mut sha3_512incctx); +} +extern "C" { + pub fn sha3_512(output: *mut u8, input: *const u8, inlen: usize); +} diff --git a/sys/pqclean/src/lib.rs b/sys/pqclean/src/lib.rs new file mode 100644 index 000000000..d67ec8857 --- /dev/null +++ b/sys/pqclean/src/lib.rs @@ -0,0 +1,2 @@ +mod bindings; +pub use bindings::*;